不同提交方式传值差异
form表单提交
可以看到Content-Type为application/x-www-form-urlencoded。
值得形式是以key1=value1&key2=value2的形式提交的。
ajax提交
图片.png
vue的axios方式提交
1.当我们传递字符串的时候,Content-Type自动转为xxx-form-xxx的形式。当为对象的时候,自动转化为xxx/json。
2.字符串的时候以key1=val1&key2=val2的形式体现,对象以JSON字符串形式体现。
以上来源于:https://segmentfault.com/a/1190000018774494?utm_medium=referral&utm_source=tuicool
springsecurity的login登录后端默认采用的接收方式是form表单提交,当前端传输数据设置Content-Type: application/json时,后端将接收不到数据。
springsecurity登录前端传值后端接收不到
springsecurity
接收登录请求后会经过用户认证的拦截器UsernamePasswordAuthenticationFilter.class
,该类的obtainUsername
用于接收前端请求数据。
protected String obtainUsername(HttpServletRequest request) {
return request.getParameter(this.usernameParameter);
}
默认的getParameter
会调用HttpServletRequestImpl.class
的getParameter
方法,可以看到是从form中取的。
public String getParameter(String name) {
if (this.queryParameters == null) {
this.queryParameters = this.exchange.getQueryParameters();
}
Deque<String> params = (Deque)this.queryParameters.get(name);
if (params == null) {
FormData parsedFormData = this.parseFormData();
if (parsedFormData != null) {
FormValue res = parsedFormData.getFirst(name);
return res != null && !res.isFileItem() ? res.getValue() : null;
} else {
return null;
}
} else {
return (String)params.getFirst();
}
}
当我们前台需要通过application/json
传输数据时,可以自定义一个拦截器继承UsernamePasswordAuthenticationFilter
通过重写obtainUsername()
和obtainPassword()
来修改获取数据的方式。
public class UserAuthenticationFilter extends UsernamePasswordAuthenticationFilter {
private ThreadLocal<Map<String,String>> threadLocal = new ThreadLocal<>();
@Override
protected String obtainPassword(HttpServletRequest request) {
String password = this.getBodyParams(request).get(super.SPRING_SECURITY_FORM_PASSWORD_KEY);
threadLocal.remove();
if(!StringUtils.isEmpty(password)){
return password;
}
return super.obtainPassword(request);
}
@Override
protected String obtainUsername(HttpServletRequest request) {
String username = this.getBodyParams(request).get(super.SPRING_SECURITY_FORM_USERNAME_KEY);
if(!StringUtils.isEmpty(username)){
return username;
}
return super.obtainUsername(request);
}
/**
* 获取body参数 body中的参数只能获取一次
* @param request
* @return
*/
private Map<String,String> getBodyParams(HttpServletRequest request) {
Map<String, String> bodyParams = threadLocal.get();
if (bodyParams == null) {
ObjectMapper objectMapper = new ObjectMapper();
try {
InputStream is = request.getInputStream();
bodyParams = objectMapper.readValue(is, Map.class);
} catch (IOException e) {
}
if (bodyParams == null) {
bodyParams = new HashMap<>();
}
threadLocal.set(bodyParams);
}
return bodyParams;
}
}