javascript
springboot整合spring security——第三章异常处理 -凯发k8官方网
文章目录
- 一、常见异常
- 二、源码分析
- 三、处理异常
- 四、拓展spring security authenticationprovider用法及关闭不隐藏usernotfoundexception的解决
不知道你有没有注意到,当我们登陆失败时候,spring security 帮我们跳转到了 /login?error url,奇怪的是不管是控制台还是网页上都没有打印错误信息。
这是因为首先 /login?error 是 spring security 默认的失败 url,其次如果你不手动处理这个异常,这个异常是不会被处理的。
代码地址:https://github.com/fadehub/spring-boot-learn/tree/master/spring-boot-security-3
一、常见异常
我们先来列举下一些 spring security 中常见的异常:
- usernamenotfoundexception(用户不存在)
- disabledexception(用户已被禁用)
- badcredentialsexception(坏的凭据)
- lockedexception(账户锁定)
- accountexpiredexception (账户过期)
- credentialsexpiredexception(证书过期)
- …
以上列出的这些异常都是 authenticationexception 的子类,然后我们来看看 spring security 如何处理 authenticationexception 异常的。.
二、源码分析
我们知道异常处理一般在过滤器中处理,我们在 abstractauthenticationprocessingfilter 中找到了对 authenticationexception 的处理:
(1)在 dofilter() 中,捕捉了 authenticationexception 异常,并交给了 unsuccessfulauthentication() 处理。
(2)在 unsuccessfulauthentication() 中,转交给了 simpleurlauthenticationfailurehandler 类的 onauthenticationfailure() 处理。
(3)在onauthenticationfailure()中,simpleurlauthenticationfailurehandler实现类,首先判断有没有设置defaultfailureurl。
如果没有设置,直接返回 401 错误,即 httpstatus.unauthorized 的值。
如果设置了,首先执行 saveexception() 方法。然后判断 forwardtodestination ,即是否是服务器跳转,默认使用重定向即客户端跳转。
(4)在 saveexception() 方法中,首先判断forwardtodestination,如果使用服务器跳转则写入 request,客户端跳转则写入 session。写入名为 spring_security_last_exception ,值为 authenticationexception。
至此 spring security 完成了异常处理,总结一下流程:
–> abstractauthenticationprocessingfilter.dofilter()
–> abstractauthenticationprocessingfilter.unsuccessfulauthentication()
–> simpleurlauthenticationfailurehandler.onauthenticationfailure()
–> simpleurlauthenticationfailurehandler.saveexception()
三、处理异常
上面源码说了那么多,真正处理起来很简单,我们只需要指定错误的url,然后再该方法中对异常进行处理即可。
(1)指定错误url,websecurityconfig中添加.failure
@configuration @enablewebsecurity @enableglobalmethodsecurity(prepostenabled = true) public class websecurityconfig extends websecurityconfigureradapter {@autowiredprivate customuserdetailsservice userdetailsservice;@autowiredprivate datasource datasource;@overrideprotected void configure(authenticationmanagerbuilder auth) throws exception {auth.authenticationprovider(authenticationprovider());}@beanpublic daoauthenticationprovider authenticationprovider() {daoauthenticationprovider provider = new daoauthenticationprovider();provider.sethideusernotfoundexceptions(false);provider.setuserdetailsservice(userdetailsservice);provider.setpasswordencoder(new passwordencoder() {@overridepublic string encode(charsequence charsequence) {return charsequence.tostring();}@overridepublic boolean matches(charsequence charsequence, string s) {return s.equals(charsequence.tostring());}});return provider;}/*** 数据库存储* @param http* @throws exception*/@overrideprotected void configure(httpsecurity http) throws exception {http.authorizerequests().anyrequest().authenticated().and().formlogin().loginpage("/login")// 设置登陆成功页.defaultsuccess.permitall().failurehandler(new simpleurlauthenticationfailurehandler())//登录失败url.failureforward.and()// 自定义登陆用户名和密码参数,默认为username和password// .usernameparameter("username")// .passwordparameter("password").logout().permitall()//基于内存自动登录.and().rememberme().tokenrepository(persistenttokenrepository()).tokenvalidityseconds(60) ;http.csrf().disable();}@beanpublic persistenttokenrepository persistenttokenrepository() {jdbctokenrepositoryimpl tokenrepository = new jdbctokenrepositoryimpl();tokenrepository.setdatasource(datasource);// 如果token表不存在,使用下面语句可以初始化该表;若存在,请注释掉这条语句,否则会报错。 // tokenrepository.setcreatetableonstartup(true);return tokenrepository;}@overridepublic void configure(websecurity web) throws exception {// 设置拦截忽略文件夹,可以对静态资源放行web.ignoring().antmatchers("/css/**", "/js/**");}}对应controller
@requestmapping("/login/error")public void loginerror(httpservletrequest req, httpservletresponse resp) {resp.setcontenttype("text/html;charset=utf-8");authenticationexception exception =(authenticationexception) req.getattribute("spring_security_last_exception");try {resp.getwriter().write(exception.tostring());}catch (ioexception e) {e.printstacktrace();}}一定是取req.getattribuate(“spring_security_last_exception”)才能取出异常信息。
四、拓展spring security authenticationprovider用法及关闭不隐藏usernotfoundexception的解决
问题是用户登录失败(用户不存在或密码错误)之后,security框架直接返回的是验证失败。而我的需求是将用户不存在和密码错误区分开来,然后做不同的后续工作。
用户不存在返回错误信息为:usernamenotfoundexception
密码错误返回错误信息为:badcredentialsexception
usernotfoundexception异常是在daoauthenticationprovider中被屏蔽掉的,而daoauthenticationprovider中有个属性hideusernotfoundexceptions,默认是ture,也就是说要想抛出usernotfoundexception,需要把hideusernotfoundexceptions设为false。
于是增加了一个daoauthenticationprovider的配置
如果我们配置daoauthenticationprovider一定要把
auth .userdetailsservice(userdetailsservice)
.passwordencoder(passwordencoder());
这两行代码删掉,否则还是不会返回我们希望的错误信息!!!
总结
以上是凯发k8官方网为你收集整理的springboot整合spring security——第三章异常处理的全部内容,希望文章能够帮你解决所遇到的问题。
- 上一篇: springboot集成spring s
- 下一篇: springboot 整合securit