spring security主要有两大异常,登录时认证失败异常401,及请求时没有权限异常403。
AuthenticationException(401)
登录不成功,如密码错误等可抛出BadCredentialsException,它是AuthenticationException的子类。
if (!code.equals("123")) {
throw new BadCredentialsException("验证码错误");
}
发生这种异常时,会跳转到认证失败url,参考第1篇。跳转后通过以下方法可获取AuthenticationException异常信息
System.out.println(session.getAttribute("SPRING_SECURITY_LAST_EXCEPTION"));
输出如下,可根据不同的异常类型和message,对前端进行响应。
AccessDeniedException(403)
已登录成功,但是请求的url超出其权限,默认会响应403状态码,你也可以手动设置响应
protected void configure(HttpSecurity http) throws Exception {
http
.exceptionHandling()
.accessDeniedHandler(accessDeniedHandler());//处理AccessDeniedException
}
@Bean
public AccessDeniedHandler accessDeniedHandler(){
return new AccessDeniedHandler(){
public void handle(HttpServletRequest request, HttpServletResponse response,
AccessDeniedException accessDeniedException) throws IOException, ServletException {
response.setContentType("text/html;charset=utf-8");
response.getWriter().print("非法请求");
response.setStatus(403);
}
};
}
AuthenticationEntryPoint
如果用户在未登录状态下直接请求需要登录的接口,应该报401,然而spring security默认会报403。因为spring security的未登录用户会拥有一个已认证的匿名权限,此时会认为其没有权限所以报403。可手动配置
protected void configure(HttpSecurity http) throws Exception {
http
.exceptionHandling()
.authenticationEntryPoint(authenticationEntryPoint());//认证端点
}
@Bean
public AuthenticationEntryPoint authenticationEntryPoint (){
return new AuthenticationEntryPoint() {
public void commence(HttpServletRequest request, HttpServletResponse response,
AuthenticationException authException) throws IOException, ServletException {
response.setContentType("text/html;charset=utf-8");
response.getWriter().print("请登录");
response.setStatus(401);
}
};
}
authenticationEntryPoint其实是在没有登录时,配置自动跳转到登录页面的url,这里将其改造成前后端分离接口。
异常消息国际化
在一些默认配置中,系统抛出的异常消息默认是英文的,可配置国际化
@Bean
public MessageSource messageSource() {
ReloadableResourceBundleMessageSource messageSource = new ReloadableResourceBundleMessageSource();
messageSource.addBasenames("classpath:org/springframework/security/messages");
return messageSource;
}
AuthenticationException子类
如果要保证系统自动响应适当的中文消息,就要触发适当的异常。如第3篇讲过的4个用户状态,分别对应AccountStatusException下的四个异常。其他类型异常自行参考以下