关于spring-security 表单登录参数为null问题

写在前面

由于第一次使用SpringSecurity做登录认证模块,在此期间遇到不少的问题,在此记录下自己遇到的坑。

前端使用了axios进行数据的交互,代码如下:

        postRequest('/login', {
          username: username,
          password: password
        }).then(resp=> {
          _this.loading = false;
          if (resp.status == 200) {
            //成功
            
          } else {
            //失败
         
          }
        }, resp=> {
			//失败
        });

postRequest函数内容如下:

export const postRequest = (url, params) => {
  return axios({
      method: 'post',
      url: `${url}`,
      data: params,
      headers: {
        'Content-Type': 'application/x-www-form-urlencoded;charset=UTF-8'
      }
  })
}

服务端登录配置如下:

protected void configure(HttpSecurity http) throws Exception {
    ....
	http.loginProcessingUrl("/login")
                .usernameParameter("username")
                .passwordParameter("password");
    ....
}

服务端认证代码如下:

    public UserDetails loadUserByUsername(String s) throws UsernameNotFoundException {
        User user= userService.loadUserByUsername(s);
        if(user==null){
            return new User();
        }
        List<Role> roles = rolesService.getRoleByUid(user.getId());
        user.setRoles(roles);
        return user;
    }

前端进行登录请求的时候一直提示登录失败,查看服务端后台log如下:

根据log,查看了服务端代码,发现UserDetailsService接口中的loadUserByUsername接收到的字符串为null。所以返回了一个空的User对象,导致密码匹配认证不通过。所以登录失败了。

于是我使用了API调试工具进行登录测试:

发现可以登录成功,于是猜测可能是前端的交互方式有问题,于是Google了一下,发现SpringSecurity默认的登录数据是通过 key/value 的形式来传递的,默认情况下不支持 JSON格式的登录数据。 知道原因之后就好解决了,可以将axios中的参数改为key/value的方式:

           postRequest('/login','username='+username+'&password='+password).then(resp=>{
                if(resp.status==200){
                    //成功
					this.$alert('登录成功!','成功!');
                }else{
                    this.$alert('登录失败!','失败!');
                }
            },resp=>{
                _this.$alert('找不到服务器!', '失败!');
            })

或者使用qs库将Json对象以 k=v的格式进行格式化

export const postRequest = (url, params) => {
  return axios({
      method: 'post',
      url: `${base}${url}`,
      data: qs.stringify(params),
  })
}

这样就可以成功登录,问题解决。