2016-12-22 3 views
1

Я реализую пользовательский 'AuthenticationProvider'. Если не аутентифицирован, я делаю исключение внутри функции «authenticate», как показано ниже.Захват исключения в AuthenticationProvider

public class DelegatingLdapAuthenticationProvider implements AuthenticationProvider { 

    private ActiveDirectoryLdapAuthenticationProvider primaryProvider; 
    private List<ActiveDirectoryLdapAuthenticationProvider> secondaryProviders = new ArrayList<>(); 

    public DelegatingLdapAuthenticationProvider() { 

    } 

    @Override 
    public Authentication authenticate(Authentication authentication) throws AuthenticationException { 
     Authentication result = null; 
     AuthenticationException exception = null; 
     try { 
      result = primaryProvider.authenticate(authentication); 
     } catch (AuthenticationException e) { 
      exception = e; 
      for (ActiveDirectoryLdapAuthenticationProvider secondaryProvider : secondaryProviders) { 
       try { 
        result = secondaryProvider.authenticate(authentication); 
        if (result.isAuthenticated()) { 
          break; 
        } 
       } catch (AuthenticationException e1) { 
          exception = e; 
       } 
      } 
     } 
     if (result == null || !result.isAuthenticated()) { 
      throw exception; 
    } 

    return result; 
} 

У меня есть глобальный обработчик исключений, как показано ниже.

Когда исключение выбрасывается внутри функции «authenticate», глобальный обработчик исключений не вызывается. За всеми остальными исключениями он называется. Я хочу поймать исключение внутри глобального обработчика исключений и возвратить сообщение об ошибке. Как я могу это сделать? Любая помощь оценивается. Заранее спасибо.

+1

Вы действительно подтвердили, что исключение выбрасывается или ваш провайдер вызывается в первую очередь? – pvg

ответ

1

GlobalExceptionHandler для обработчика исключений контроллера, но AuthenticationProvider еще в фильтре, если вы хотите, чтобы обработчик AuthenticationException, вам нужно обработать его реализовать AuthenticationEntryPoint и переопределить метод commence.

public void commence(HttpServletRequest request, HttpServletResponse response, 
     AuthenticationException authException) throws IOException, ServletException 

AuthenticationException и AccessDeniedException уже обработаны ExceptionTranslationFilter. Вам просто нужно вводить AuthenticationEntryPoint и AccessDeniedHandler (которые обрабатывают AccessDeniedException)

Или вы можете поймать эти исключения в фильтре, а затем обработать его в файлер, как AuthenticationFailureHandler в AbstractAuthenticationProcessingFilter

0

провайдер аутентификации вызывается до обработчика исключений контроллера имеет шанс поймать исключения.

Вы можете переопределить AuthenticationFailureHandler для обработки исключений на уровне цепи фильтра безопасности, обратите внимание на examples

Поведение, как описано в documentation:

Фильтр вызовов сконфигурированной AuthenticationManager для обработки каждого запроса аутентификации. Назначение после успешной аутентификации или сбой аутентификации контролируется интерфейсами стратегии аутентификацииSuccessHandler и AuthenticationFailureHandler соответственно. Фильтр имеет свойства, которые позволяют установить их, так что вы можете настроить поведение полностью

0

Как @chaoluo уже сказал, что вы должны реализовать AuthenticationEntryPoint и переопределить метод commence. Если вы хотите вернуть объект JSON, вы можете сделать следующее:

@Override 
public void commence(HttpServletRequest request, HttpServletResponse response, AuthenticationException authException) 
      throws IOException, ServletException { 

    response.setStatus(HttpServletResponse.SC_UNAUTHORIZED); 
    response.setContentType(MediaType.APPLICATION_JSON_VALUE); 
    //create errorObj 
    PrintWriter writer = response.getWriter(); 
    mapper.writeValue(writer, errorObj); 
    writer.flush(); 
} 
Смежные вопросы