Обычно вы используете AuthenticationFailureHandler
для инкапсуляции логики, которая запускается AuthenticationException
.X509AuthenticationFilter
обычно вызывает PreAuthenticatedAuthenticationProvider
для аутентификации, что, в свою очередь, вызывает метод loadUserByUsername(...)
из UserDetailsService
.Любой AuthenticationException
, выданный UserDetailsService
, перехватывается фильтром, и управление передается зарегистрированному AuthenticationFailureHandler
.Это включает UsernameNotFoundException
.
Однако , если вы используете X509Configurer
, (http.x509()
), нет способа установить обработчик непосредственно на фильтре.Поэтому, как только выдается исключение, X509AuthenticationFilter
перехватывает его, видит, что обработчик по умолчанию отсутствует, а затем просто передает запрос следующему фильтру в цепочке фильтров.
Одним из способов обойти это может бытьпредоставьте пользовательскую X509AuthenticationFilter
.
In WebSecurityConfigurerAdapter
:
@Autowired
private AuthenticationFailureHandler customFailureHandler;
@Autowired
private UserService customUserService;
@Bean(name = BeanIds.AUTHENTICATION_MANAGER)
@Override
public AuthenticationManager authenticationManagerBean() throws Exception {
return super.authenticationManagerBean();
}
protected void configure(HttpSecurity http) throws Exception {
...
http.x509().x509AuthenticationFilter(myX509Filter())
.userDetailsService(customUserService)
...
}
private X509AuthenticationFilter myX509Filter() {
X509AuthenticationFilter myCustomFilter = new X509AuthenticationFilter();
myCustomFilter.setAuthenticationManager(authenticationManagerBean());
...
myCustomFilter.setContinueFilterChainOnUnsuccessfulAuthentication(false);
myCustomFilter.setAuthenticationFailureHandler(customFailureHandler);
return myCustomFilter;
}
Затем вы можете написать собственную реализацию AuthenticationFailureHandler
и представить ее в виде bean-компонента.