详解春季安全如何配置JSON登录
春季安全用了也有一段时间了,弄过异步和多数据源登录,也看过一点源码,最近弄休息,然后顺便搭oauth2,前端用json来登录,没想到春季安全默认居然不能获取请求中的json数据,谷歌一波后只在stackoverflow找到一个回答比较靠谱,还是得要重写过滤器,于是在这里填一波坑。
准备工作
基本的春季安全配置就不说了,网上一堆例子,只要弄到普通的表单登录和自定义用户详细信息服务就可以。因为需要重写过滤器,所以需要对春季安全的工作流程有一定的了解,这里简单说一下春季安全的原理。
春季安全是基于javax.servlet.Filter的,因此才能在spring mvc(DispatcherServlet基于Servlet)前起作用。
usernamepassword authenticationfilter :实现过滤器接口,负责拦截登录处理的url,帐号和密码会在这里获取,然后封装成证明交给身份验证管理器进行认证工作认证:贯穿整个认证过程,封装了认证的用户名,密码和权限角色等信息,接口有一个布尔isAuthenticated()方法来决定该证明认证成功没;身份验证管理器:认证管理器,但本身并不做认证工作,只是做个管理者的角色。例如默认实现供应商经理会持有一个AuthenticationProvider数组,把认证工作交给这些AuthenticationProvider,直到有一个AuthenticationProvider完成了认证工作认证提供程序:认证提供者,默认实现,也是最常使用的是DaoAuthenticationProvider。我们在配置时一般重写一个用户详细信息服务来从数据库获取正确的用户名密码,其实就是配置了DaoAuthenticationProvider的用户详细信息服务属性,DaoAuthenticationProvider会做帐号和密码的比对,如果正常就返回给身份验证管理器一个验证成功的证明看usernamepassworauthenticationfilter源码里的获取用户名和获取密码方法只是简单地调用request.getParameter方法,因此如果用json发送用户名和密码会导致DaoAuthenticationProvider检查密码时为空,抛出不良信用评级异常。
/** *允许子类覆盖密码的组成,例如*包括附加值和分隔符* p *例如,如果除了密码之外,还需要邮政编码/邮政编码,则可以使用此选项。应该使用管道(|)等分隔符来分隔*密码和扩展值codeAuthenticationDao/代码需要*以相应的方式生成预期的密码* /p * * @param请求以便可以检索请求属性* * @将在代码验证/代码*请求令牌中显示的密码返回给codeAuthenticationManager/code */受保护的字符串获取密码(HttpServletrequest请求){退货请求。getparameter(password parameter);} /** *允许子类覆盖用户名的组成,例如通过*包括附加值和分隔符* * @参数请求以便可以检索请求属性* * @将在代码验证/代码*请求令牌中呈现的用户名返回给codeAuthenticationManager/code */受保护的字符串获取用户名(HttpServletRequest请求请求){退货请求。getparameter(usernameParameter);}重写UsernamePasswordAnthenticationFilter
上面UsernamePasswordAnthenticationFilter的获取用户名和获取密码方法的注释已经说了,可以让子类来自定义用户名和密码的获取工作。但是我们不打算重写这两个方法,而是重写它们的调用者尝试身份验证方法,因为json反序列化毕竟有一定消耗,不会反序列化两次,只需要在重写的尝试身份验证方法中检查是否json登录,然后直接反序列化返回证明对象即可。这样我们没有破坏原有的获取流程,还是可以重用父类原有的尝试身份验证方法来处理表单登录。
/** *支持休息登录(json登录)和表单登录的身份验证过滤器.* @作者陈焕明*/公共类CustomAuthenticationFilter扩展usernamepassworauthenticationfilter { @覆盖公共身份验证尝试身份验证(HttpServletRequest请求,HttpServletResponse响应)在内容类型为json if(request.getContentType())时引发AuthenticationException {//尝试身份验证等于(媒体类型.APPLICATION _ JSON _ UTF8 _ VALUE)| |请求。GetContentType().等于(媒体类型.APPLICATION _ JSON _ VALUE)){//使用杰克逊反序列化JSON对象映射器=新对象映射器();usernamepassworauthenticationtoken authRequest=null;try(InputStream is=request。getinputstream()){ AuthenticationBean AuthenticationBean=映射器。readvalue(是,AuthenticationBean。类);authRequest=new usernamepassword authenticationtoken(authenticationbean。getusername()、authenticationbean。getpassword());} catch(IOexception e){ e . print stack trace();新用户名称密码身份验证令牌(""、"");}最后{ setDetails(request,authRequest);返回this.getAuthenticationManager().验证(authRequest);} }//将其传输到usernamepassworauthenticationfilter else { return super。尝试验证(请求,响应);} }}封装的身份验证豆类,用了龙目岛简化代码(龙目帮我们写吸气剂和作曲者方法而已)
@Getter@Setterpublic类AuthenticationBean {私有字符串用户名;私有字符串密码;} WebSecurityConfigurerAdapter配置
重写过滤器不是问题,主要是怎么把这个过滤器加到春季安全的众多过滤器里面。
@ overrided protected void configure(HttpSecurity Http)引发异常{ http .cors().和()。antMatcher('/** ').authorizeRequests().antMatchers('/','/login** ').permitAll().anyRequest().已验证()//这里必须要写formLogin(),不然原有的usernamepassworauthenticationfilter不会出现,也就无法配置我们重新的usernamepassworauthenticationfilter .和()。formLogin().loginPage('/').和()。csrf().disable();//用重写的过滤器替换掉原有的usernamepassword authenticationfilter http。addfilterat(customAuthenticationFilter())、usernamepassword authenticationfilter。类);}//注册自定义的usernamepassworauthenticationfilter @ bean customAuthenticationFilter customAuthenticationFilter()引发异常{ customAuthenticationFilter=new customAuthenticationFilter();过滤器。setauthenticationsuccesshandler(new Successhandler());过滤器。setauthenticationfailure处理程序(新的失败处理程序());过滤器。setfilterprocesssurl('/log in/self ');//这句很关键,重用网络安全配置雷达图配置的身份验证管理器,不然要自己组装身份验证管理器筛选器。setauthenticationmanager(authenticationManagerBean());返回过滤器;}题外话,如果搭自己的oauth2的服务器,需要让春季安全警报2共享同一个AuthenticationManager(源码的解释是这样写可以暴露出这个身份验证管理器,也就是注册到春季国际奥委会)
@ Override @ Bean//web和oauth公共身份验证管理器身份验证管理器Bean()的共享身份验证管理器引发异常{返回超级。authenticationManagerBean();}至此春天安全就支持表单登录和异步json登录了。
参考来源
stackoverflow的问答
以上就是本文的全部内容,希望对大家的学习有所帮助,也希望大家多多支持我们。
版权声明:详解春季安全如何配置JSON登录是由宝哥软件园云端程序自动收集整理而来。如果本文侵犯了你的权益,请联系本站底部QQ或者邮箱删除。

















