Spring Security自定义验证失败处理器AuthenticationFailureHandler
Spring Security的AuthenticationManager用来处理验证的请求,处理的结果分两种:
- 验证成功:结果由AuthenticationSuccessHandler处理
- 验证失败:结果由交给AuthenticationFailureHandler处理。
在Spring Security内置了几种验证失败处理器:
- DelegatingAuthenticationFailureHandler将AuthenticationException子类委托给不同的AuthenticationFailureHandler,这意味着我们可以为AuthenticationException的不同实例创建不同的行为
- ExceptionMappingAuthenticationFailureHandler根据AuthenticationException的完整类名将用户重定向到特定的URL
- SimpleUrlAuthenticationFailureHandler是默认使用的组件,如果指定,它会将用户重定向到failureUrl;否则,它只会返回401响应
自定义AuthenticationFailureHandler
如果想自定义验证失败处理器,需要实现AuthenticationFailureHandler接口。AuthenticationFailureHandler接口源码如下:
package org.springframework.security.web.authentication;
public interface AuthenticationFailureHandler {
/**
* 认证失败时会调用此方法
* @param request 出现认证失败时所处于的请求.
* @param response 对应上面请求的响应对象.
* @param exception 携带认证失败原因的认证失败异常对象
* request.
*/
void onAuthenticationFailure(HttpServletRequest request,
HttpServletResponse response, AuthenticationException exception)
throws IOException, ServletException;
}
实现一个简单的自定义AuthenticationFailureHandler,如下:
public class CustomAuthenticationFailureHandler
implements AuthenticationFailureHandler {
private ObjectMapper objectMapper = new ObjectMapper();
@Override
public void onAuthenticationFailure(HttpServletRequest request,HttpServletResponse response,AuthenticationException exception)
throws IOException, ServletException {
response.setStatus(HttpStatus.UNAUTHORIZED.value());
Map<String, Object> data = new HashMap<>();
data.put("exception", exception.getMessage());
response.getOutputStream().println(objectMapper.writeValueAsString(data));
}
}
这里只是简单的返回了一个验证失败的http状态码401,并把异常信息返回。
配置自定义AuthenticationFailureHandler
Spring Security默认是使用SimpleUrlAuthenticationFailureHandler,在配置中修改为自定义的AuthenticationFailureHandler。
@Configuration
@EnableWebSecurity
public class SecurityConfiguration
extends WebSecurityConfigurerAdapter {
@Override
protected void configure(AuthenticationManagerBuilder auth)
throws Exception {
auth
.inMemoryAuthentication()
.withUser("test")
.password("test")
.roles("USER");
}
@Override
protected void configure(HttpSecurity http)
throws Exception {
http
.authorizeRequests()
.anyRequest()
.authenticated()
.and()
.formLogin()
.failureHandler(customAuthenticationFailureHandler());
}
@Bean
public AuthenticationFailureHandler customAuthenticationFailureHandler() {
return new CustomAuthenticationFailureHandler();
}
}
可以注意到在HttpSecurity上调用了failureHandler来配置自定义的AuthenticationFailureHandler.