SpringBoot集成SpringSecurity,获取不到RequestBody处理

SpringSecurity的用户验证,只支持requset param格式的,现在的系统都是前后端分离,传过来的参数也是requesbody的json格式,默认的验证方式通不过。
通过查看源码,发现用户验证会走到UsernamePasswordAuthenticationFilter过滤器,然后走到attemptAuthentication方法,然后通过obtainUsername获取用户名,通过obtainPassword获取密码
知道了原理就好办了,我们新建一个Filter,继承UsernamePasswordAuthenticationFilter,再重写obtainUsernameobtainPassword两个方法

public class LoginFilter 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);
        if(!StrUtil.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(!StrUtil.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;
    }
}

然后在SprintSecurity的配置类中,添加这个过滤器

  private LoginFilter userAuthenticationFilterBean() throws Exception {
      LoginFilter userAuthenticationFilter = new LoginFilter();
      userAuthenticationFilter.setAuthenticationManager(super.authenticationManager());
      //登录成功的处理
      userAuthenticationFilter.setAuthenticationSuccessHandler(authenticationSuccessHandler);
      //登录失败的处理
      userAuthenticationFilter.setAuthenticationFailureHandler(authenticationFailureHandler);
      return userAuthenticationFilter;
  }

然后在configure(HttpSecurity http)中添加过滤器

protected void configure(HttpSecurity http) throws Exception {
    ......省略其他配置
    http.addFilterAt(userAuthenticationFilterBean(), UsernamePasswordAuthenticationFilter.class);
}

完成。

posted @   O。O  阅读(701)  评论(0编辑  收藏  举报
相关博文:
阅读排行:
· TypeScript + Deepseek 打造卜卦网站:技术与玄学的结合
· Manus的开源复刻OpenManus初探
· AI 智能体引爆开源社区「GitHub 热点速览」
· 从HTTP原因短语缺失研究HTTP/2和HTTP/3的设计差异
· 三行代码完成国际化适配,妙~啊~
点击右上角即可分享
微信分享提示