文章详情

短信预约-IT技能 免费直播动态提醒

请输入下面的图形验证码

提交验证

短信预约提醒成功

使用Spring Security怎么JSON进行配置并登录

2023-05-31 08:46

关注

这期内容当中小编将会给大家带来有关使用Spring Security怎么JSON进行配置并登录,文章内容丰富且以专业的角度为大家分析和叙述,阅读完这篇文章希望大家可以有所收获。

准备工作

基本的spring security配置就不说了,网上一堆例子,只要弄到普通的表单登录和自定义UserDetailsService就可以。因为需要重写Filter,所以需要对spring security的工作流程有一定的了解,这里简单说一下spring security的原理。

使用Spring Security怎么JSON进行配置并登录

spring security 是基于javax.servlet.Filter的,因此才能在spring mvc(DispatcherServlet基于Servlet)前起作用。

  1. UsernamePasswordAuthenticationFilter:实现Filter接口,负责拦截登录处理的url,帐号和密码会在这里获取,然后封装成Authentication交给AuthenticationManager进行认证工作

  2. Authentication:贯穿整个认证过程,封装了认证的用户名,密码和权限角色等信息,接口有一个boolean isAuthenticated()方法来决定该Authentication认证成功没;

  3. AuthenticationManager:认证管理器,但本身并不做认证工作,只是做个管理者的角色。例如默认实现ProviderManager会持有一个AuthenticationProvider数组,把认证工作交给这些AuthenticationProvider,直到有一个AuthenticationProvider完成了认证工作。

  4. AuthenticationProvider:认证提供者,默认实现,也是最常使用的是DaoAuthenticationProvider。我们在配置时一般重写一个UserDetailsService来从数据库获取正确的用户名密码,其实就是配置了DaoAuthenticationProvider的UserDetailsService属性,DaoAuthenticationProvider会做帐号和密码的比对,如果正常就返回给AuthenticationManager一个验证成功的Authentication

看UsernamePasswordAuthenticationFilter源码里的obtainUsername和obtainPassword方法只是简单地调用request.getParameter方法,因此如果用json发送用户名和密码会导致DaoAuthenticationProvider检查密码时为空,抛出BadCredentialsException。

  protected String obtainPassword(HttpServletRequest request) {    return request.getParameter(passwordParameter);  }    protected String obtainUsername(HttpServletRequest request) {    return request.getParameter(usernameParameter);  }

重写UsernamePasswordAnthenticationFilter

上面UsernamePasswordAnthenticationFilter的obtainUsername和obtainPassword方法的注释已经说了,可以让子类来自定义用户名和密码的获取工作。但是我们不打算重写这两个方法,而是重写它们的调用者attemptAuthentication方法,因为json反序列化毕竟有一定消耗,不会反序列化两次,只需要在重写的attemptAuthentication方法中检查是否json登录,然后直接反序列化返回Authentication对象即可。这样我们没有破坏原有的获取流程,还是可以重用父类原有的attemptAuthentication方法来处理表单登录。

public class CustomAuthenticationFilter extends UsernamePasswordAuthenticationFilter {  @Override  public Authentication attemptAuthentication(HttpServletRequest request, HttpServletResponse response) throws AuthenticationException {    //attempt Authentication when Content-Type is json    if(request.getContentType().equals(MediaType.APPLICATION_JSON_UTF8_VALUE)        ||request.getContentType().equals(MediaType.APPLICATION_JSON_VALUE)){      //use jackson to deserialize json      ObjectMapper mapper = new ObjectMapper();      UsernamePasswordAuthenticationToken authRequest = null;      try (InputStream is = request.getInputStream()){        AuthenticationBean authenticationBean = mapper.readValue(is,AuthenticationBean.class);        authRequest = new UsernamePasswordAuthenticationToken(            authenticationBean.getUsername(), authenticationBean.getPassword());      }catch (IOException e) {        e.printStackTrace();        new UsernamePasswordAuthenticationToken(            "", "");      }finally {        setDetails(request, authRequest);        return this.getAuthenticationManager().authenticate(authRequest);      }    }    //transmit it to UsernamePasswordAuthenticationFilter    else {      return super.attemptAuthentication(request, response);    }  }}

封装的AuthenticationBean类,用了lombok简化代码(lombok帮我们写getter和setter方法而已)

@Getter@Setterpublic class AuthenticationBean {  private String username;  private String password;}

WebSecurityConfigurerAdapter配置

重写Filter不是问题,主要是怎么把这个Filter加到spring security的众多filter里面。

@Overrideprotected void configure(HttpSecurity http) throws Exception {  http      .cors().and()      .antMatcher("/**").authorizeRequests()      .antMatchers("/", "/login**").permitAll()      .anyRequest().authenticated()      //这里必须要写formLogin(),不然原有的UsernamePasswordAuthenticationFilter不会出现,也就无法配置我们重新的UsernamePasswordAuthenticationFilter      .and().formLogin().loginPage("/")      .and().csrf().disable();  //用重写的Filter替换掉原有的UsernamePasswordAuthenticationFilter  http.addFilterAt(customAuthenticationFilter(),  UsernamePasswordAuthenticationFilter.class);}//注册自定义的UsernamePasswordAuthenticationFilter@BeanCustomAuthenticationFilter customAuthenticationFilter() throws Exception {  CustomAuthenticationFilter filter = new CustomAuthenticationFilter();  filter.setAuthenticationSuccessHandler(new SuccessHandler());  filter.setAuthenticationFailureHandler(new FailureHandler());  filter.setFilterProcessesUrl("/login/self");  //这句很关键,重用WebSecurityConfigurerAdapter配置的AuthenticationManager,不然要自己组装AuthenticationManager  filter.setAuthenticationManager(authenticationManagerBean());  return filter;}

题外话,如果搭自己的oauth3的server,需要让spring security oauth3共享同一个AuthenticationManager(源码的解释是这样写可以暴露出这个AuthenticationManager,也就是注册到spring ioc)

@Override@Bean // share AuthenticationManager for web and oauthpublic AuthenticationManager authenticationManagerBean() throws Exception {  return super.authenticationManagerBean();}

上述就是小编为大家分享的使用Spring Security怎么JSON进行配置并登录了,如果刚好有类似的疑惑,不妨参照上述分析进行理解。如果想知道更多相关知识,欢迎关注编程网行业资讯频道。

阅读原文内容投诉

免责声明:

① 本站未注明“稿件来源”的信息均来自网络整理。其文字、图片和音视频稿件的所属权归原作者所有。本站收集整理出于非商业性的教育和科研之目的,并不意味着本站赞同其观点或证实其内容的真实性。仅作为临时的测试数据,供内部测试之用。本站并未授权任何人以任何方式主动获取本站任何信息。

② 本站未注明“稿件来源”的临时测试数据将在测试完成后最终做删除处理。有问题或投稿请发送至: 邮箱/279061341@qq.com QQ/279061341

软考中级精品资料免费领

  • 历年真题答案解析
  • 备考技巧名师总结
  • 高频考点精准押题
  • 2024年上半年信息系统项目管理师第二批次真题及答案解析(完整版)

    难度     807人已做
    查看
  • 【考后总结】2024年5月26日信息系统项目管理师第2批次考情分析

    难度     351人已做
    查看
  • 【考后总结】2024年5月25日信息系统项目管理师第1批次考情分析

    难度     314人已做
    查看
  • 2024年上半年软考高项第一、二批次真题考点汇总(完整版)

    难度     433人已做
    查看
  • 2024年上半年系统架构设计师考试综合知识真题

    难度     221人已做
    查看

相关文章

发现更多好内容

猜你喜欢

AI推送时光机
位置:首页-资讯-后端开发
咦!没有更多了?去看看其它编程学习网 内容吧
首页课程
资料下载
问答资讯