异常处理
我们在这里只是介绍下Spring Security的简单的异常的抓取。并不做源码的分析。
一, 常见的异常
- UsernameNotFoundException
用户不存在,但是我程序中抛出该异常的时候,常常抓取到的是BadCredentialsException异常
这种情况,我们可以自定义异常,继承AuthenticationException 类 - DisabledException
用户已经被禁用 - BadCredentialsException
坏的凭证 - LockedException
账户锁定 - AccountExpiredException
账户过期 - CredentialsExpiredException
证书过期
…
上面的这些异常都是AuthenticationException的子类。
二, spring security的异常处理过程
(1)AbstractAuthenticationProcessingFilter.doFilter()
(2)AbstractAuthenticationProcessingFilter.unsuccessfulAuthentication()
(3)SimpleUrlAuthenticationFailureHandler.onAuthenticationFailure()
- 这个方法中,首先会判断有没有设置的defaultFailureUrl
- 如果没有设置,直接返回401错误,即HttpStatus.UNAUTHORIZED
- 如果设置了首先会执行saveException方法,然后判断forwardToDestination,即是否服务器跳转,默认使用重定向。
(4)SimpleUrlAuthenticationFailureHandler.saveException()
- 首先判断forwardToDestination
- 如果使用服务器跳转则写入Request(转发)
- 如果使用客户端跳转则写入Session(重定向)
- 将对应的异常信息,写到SPRING_SECURITY_LAST_EXCEPTION ,值为 BadCredentialsException
三, 异常抓取代码
异常的抓取我们需要自己写一个Controller去接取配置的若出错重定向到的页面
- 配置类
/**
* 定制登陆行为
* @param http
* @throws Exception
*/
@Override
protected void configure(HttpSecurity http) throws Exception {
http.authorizeRequests()
.anyRequest().authenticated()
.and()
.formLogin().loginPage("/login")
.defaultSuccessUrl("/sayHello")
.failureUrl("/login/error")
.permitAll()
.and()
.logout().permitAll()
// 自动登录的校验
.and().rememberMe()
.tokenRepository(persistentTokenRepository())
// 声明有效时间,单位是s
.tokenValiditySeconds(60)
// 进行校验的service
.userDetailsService(userDetailsService);
// 关闭CSRF
http.csrf().disable();
}
里面的.
(1)failureUrl():这个表示的就是重定向,就是客户端跳转,写到session中
(2).failureForwardUrl():这个方法表示的是转发,就是服务端跳转,写到request中
- Controller类
@RequestMapping("/login/error")
public void loginError(HttpServletRequest request, HttpServletResponse response) {
response.setContentType("text/html;charset=utf-8");
AuthenticationException exception =
(AuthenticationException)request.getSession().getAttribute("SPRING_SECURITY_LAST_EXCEPTION");
try {
response.getWriter().write(exception.toString());
}catch (IOException e) {
e.printStackTrace();
}
}