AuthenticationException, выброшенное в AuthenticationProvider, сопоставлено с AccessDeniedException в ExceptionTranslationFilter - PullRequest
0 голосов
/ 08 мая 2019

Написав собственный AuthenticationProvider (который вызывает сервис, после которого тот вызывает внешний URL-адрес для аутентификации заданных учетных данных), я хотел настроить сообщение об ошибке, которое люди получают при сбое аутентификации, на основе сообщения, которое я передаю экземпляр AuthenticationException (поэтому e.getMessage() передано BadCredentialsExceptoin в приведенном ниже коде).

@Component
public class TapasAuthenticationProvider implements AuthenticationProvider {

    @Override
    public TapasAuthentication authenticate(Authentication authentication) throws AuthenticationException {
        String userName = authentication.getName();
        String password = authentication.getCredentials().toString();

        try {
            AuthenticationResponse authResponse = authenticationService.authenticate(userName, password);
            return new TapasAuthentication(mapToAuthenticatedUser(authResponse, userName, password), password);
        } catch (AuthenticationFailedException e) {
            // Note that AuthenticationFailedException is a self-written exception, thrown by the authenticationService.
            log.error("Authentication failed: ", e);
            throw new BadCredentialsException(e.getMessage());
        }
    }

}

Теперь я посмотрел, как отобразить AuthenticationException s, и обнаружил, что для этого следует использовать AuthenticationEntryPoint. Поэтому я создал его и добавил в свой SecuritySetup:

@Component
public class TapasAuthenticationEntryPoint implements AuthenticationEntryPoint {

    @Override
    public void commence(HttpServletRequest request, HttpServletResponse response, AuthenticationException authException)
            throws IOException, ServletException {
        System.out.println(authException.getMessage());
        // More code to be added once exception is what I expect.
    }

}

    @Autowired
    private TapasAuthenticationEntryPoint authenticationEntryPoint;

    @Override
    protected void configure(HttpSecurity http) throws Exception {
        http.sessionManagement().sessionCreationPolicy(SessionCreationPolicy.NEVER)
                .and()
                .authorizeRequests().anyRequest().authenticated().and().httpBasic()
                .and()
                .exceptionHandling().authenticationEntryPoint(authenticationEntryPoint)
                .and()
                .csrf().disable();
    }

Это успешно вызывает AuthenticationEntryPoint, но вместо BadCredentialsException я получаю InsufficientAuthenticationException. Я проверил происхождение этого исключения, и оно исходит из исключения ExceptionTranslationFilter handleSpringSecurityException. Здесь исключение оказывается AccessDeniedException вместо AuthenticationException.

    private void handleSpringSecurityException(HttpServletRequest request,
            HttpServletResponse response, FilterChain chain, RuntimeException exception)
            throws IOException, ServletException {
        if (exception instanceof AuthenticationException) {
            // I would except to enter this if-statement, but exception is not what I expect
            sendStartAuthentication(request, response, chain,
                    (AuthenticationException) exception);
        }
        else if (exception instanceof AccessDeniedException) {
            ....
            Authentication authentication = SecurityContextHolder.getContext().getAuthentication();
            if (authenticationTrustResolver.isAnonymous(authentication) || authenticationTrustResolver.isRememberMe(authentication)) {
                // Instead code comes here, and creates an InsufficientAuthenticationException.

                sendStartAuthentication(
                        request,
                        response,
                        chain,
                        new InsufficientAuthenticationException(
                            messages.getMessage(
                                "ExceptionTranslationFilter.insufficientAuthentication",
                                "Full authentication is required to access this resource")));
            }
            ...
        }
    }

Почему исключение не совпадает с моим исключением, выданным в AuthenticationProvider? И как я смогу передать данные из AuthenticationProvider обратно пользователю?

1 Ответ

0 голосов
/ 08 мая 2019

Оказывается, HttpBasicConfigurer, возвращаемый вызовом .basicSecurity(), также позволяет зарегистрировать AuthenticationEntryPoint. При такой регистрации исключение, выданное провайдером, в конце концов попадает в точку входа.

Конфигурация безопасности выглядит следующим образом:

    @Autowired
    private TapasAuthenticationEntryPoint authenticationEntryPoint;


    @Override
    protected void configure(HttpSecurity http) throws Exception {
        http.sessionManagement().sessionCreationPolicy(SessionCreationPolicy.NEVER)
                .and()
                .authorizeRequests().anyRequest().authenticated()
                .and()
                .httpBasic().authenticationEntryPoint(authenticationEntryPoint)
                .and()
                .csrf().disable();
    }
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...