Проверка x509 не проходит, прежде чем она может быть захвачена - PullRequest
0 голосов
/ 23 мая 2019

У меня есть приложение Spring Boot, использующее аутентификацию x509, которая дополнительно проверяет пользователей по базе данных. Когда пользователь получает доступ к сайту, внутренний код Spring вызывает метод loadUserByUsername, который, в свою очередь, вызывает базу данных. Все это происходит до того, как контроллер узнает, что что-то происходит. Если пользователь не найден, он создает исключение EntityNotFoundException и отображает трассировку стека в браузере пользователя.

Я использую Spring Boot Starter. Контроллер имеет код для захвата исключения и возврата сообщения «Not Authorized», но это происходит задолго до этого. Кто-нибудь еще видел это, и у вас есть обходной путь?

@Service
public class UserService implements UserDetailsService {
    public UserDetails loadUserByUsername(String dn) {
        ApprovedUser details = auService.getOne(dn);
        if (details ==  null){
            String message = "User not authorized: " + dn;
            throw new UsernameNotFoundException(message);
        }

        List<GrantedAuthority> authorities = new ArrayList<>();
        authorities.add(new SimpleGrantedAuthority("ROLE_USER"));
        if (details.isAdminUser()){
            authorities.add(new SimpleGrantedAuthority("ROLE_ADMIN_USER"));
        }
        return new AppUser(dn, "", authorities);
    }

1 Ответ

1 голос
/ 24 мая 2019

Обычно вы используете 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-компонента.

...