首页 > 编程语言 > 详细

SpringSecurity(十二):JSON登陆

时间:2021-05-21 18:22:33      阅读:16      评论:0      收藏:0      [点我收藏+]

在使用 SpringSecurity 中,大伙都知道默认的登录数据是通过 key/value 的形式来传递的,默认情况下不支持 JSON格式的登录数据,如果有这种需求,就需要自己来解决,本文主要和小伙伴来聊聊这个话题。

通过之前的分析,我们已经知道了登录参数的提取在 UsernamePasswordAuthenticationFilter 过滤器中提取的,因此我们只需要模仿UsernamePasswordAuthenticationFilter过滤器重写一个过滤器,放在UsernamePasswordAuthenticationFilter的位置即可

public class LoginFilter extends UsernamePasswordAuthenticationFilter {
    @Override
    public Authentication attemptAuthentication(HttpServletRequest request, HttpServletResponse response) throws AuthenticationException {
        if (request.getContentType().equals(MediaType.APPLICATION_JSON_UTF8_VALUE)
                || request.getContentType().equals(MediaType.APPLICATION_JSON_VALUE)) {
            ObjectMapper mapper = new ObjectMapper();
            UsernamePasswordAuthenticationToken authRequest = null;
            try (InputStream is = request.getInputStream()) {
                Map<String,String> authenticationBean = mapper.readValue(is, Map.class);
                authRequest = new UsernamePasswordAuthenticationToken(
                        authenticationBean.get("username"), authenticationBean.get("password"));
            } catch (IOException e) {
                e.printStackTrace();
                authRequest = new UsernamePasswordAuthenticationToken(
                        "", "");
            } finally {
                setDetails(request, authRequest);
                return this.getAuthenticationManager().authenticate(authRequest);
            }
        }
        else {
            return super.attemptAuthentication(request, response);
        }
    }
}

(1)首先确保进入过滤器的是POST请求
(2)根据请求的content-type判断参数是不是JSON格式,如果不是则调用父类的attemptAuthentication方法
(3)如果请求时JSON格式,则先利用jackson提供的ObjectMapper工具,将输入流转化为Map对象,然后从Map对象中提取出用户名 密码,构造出UsernamePasswordAuthenticationToken对象,进行认证
(4)其实和原UsernamePasswordAuthenticationFilter比起来,只有获取参数的方法不同,其他的都类似

接着,我们需要把这个过滤器放在过滤器链中

public class SecurityConfig extends WebSecurityConfigurerAdapter{
@Override
protected void configure(HttpSecurity http) throws Exception {
    http.authorizeRequests().anyRequest().authenticated()
            .and()
            .formLogin()
            .and().csrf().disable();
    //addFilterAt表示放在指定位置上
    http.addFilterAt(loginFilter(), UsernamePasswordAuthenticationFilter.class);
}

//注册一个AuthenticationManager实例
@Override
@Bean
public AuthenticationManager authenticationManagerBean()  throws Exception{
return super.authenticationManagerBean();
}


//注册一个过滤器实例
@Bean
LoginFilter loginFilter() throws Exception {
    LoginFilter filter = new LoginFilterFilter();

    filter.setAuthenticationManager(authenticationManagerBean());

    filter.setAuthenticationSuccessHander((req,resp.auth) ->{
    resp.setContentType("application/json;charset=utf-8");
    PrintWriter out=resp.getWriter();
    out.write(new ObjectMapper().writeValueAsString(auth));
});
    return filter
}
}

(1)重写父类的authenticationManagerBean方法,提供一个AuthenticationManager配给过滤器

(2)配置过滤器实例,为过滤器配置成功、失败处理器

(3)在HttpSecurity中使用addFilterAt方法将过滤器添加到 UsernamePasswordAuthenticationFilter的位置上

需要注意的是,我们获取AuthenticationManager实例时,有两种方法 一种是重写父类的authenticationManage()方法,一种是重写父类的authenticationManageBean()方法

区别就在于重写父类的authenticationManage()方法获得的是全局AuthenticationManager实例,重写父类的authenticationManageBean()方法获得的是局部AuthenticationManager实例

在实际应用时,我们一般都是重写父类的authenticationManageBean()方法获得局部AuthenticationManager实例

SpringSecurity(十二):JSON登陆

原文:https://www.cnblogs.com/wangstudyblog/p/14793681.html

(0)
(0)
   
举报
评论 一句话评论(0
关于我们 - 联系我们 - 留言反馈 - 联系我们:wmxa8@hotmail.com
© 2014 bubuko.com 版权所有
打开技术之扣,分享程序人生!