2016-12-22 2 views
1

사용자 정의 'AuthenticationProvider'를 구현 중입니다. 인증되지 않은 경우 아래에 표시된대로 '인증'기능 내에 예외가 발생합니다.AuthenticationProvider에서 캐칭 예외가 throw 됨

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; 
} 

다음과 같이 전역 예외 처리기가 있습니다.

@ControllerAdvice 
public class GlobalExceptionHandler { 

    @ExceptionHandler({NoPermissionException.class}) 
    @ResponseBody 
    @ResponseStatus(value = HttpStatus.FORBIDDEN) 
    public Map<String, String> noPermission(NoPermissionException e) { 
     return createErrorResponse(e, "Don't have permissions"); 
    } 

    @ExceptionHandler({Exception.class}) 
    @ResponseBody 
    @ResponseStatus(value = HttpStatus.INTERNAL_SERVER_ERROR) 
    public Map<String, String> exceptionInProcessing(Exception e) { 
     return createErrorResponse(e, "Unable to process. Unknown error occurred: " + e.getMessage()); 
    } 

    private Map<String, String> createErrorResponse(Exception e, String errorMessage) { 
     Map<String, String> errorResponse = new HashMap<>(); 
     errorResponse.put("message", errorMessage); 
     errorResponse.put("reason", e.toString()); 
     return errorResponse; 
    } 
} 

'authenticate'함수 내에 예외가 발생하면 전역 예외 처리기가 호출되지 않습니다. 다른 모든 예외의 경우 호출됩니다. 전역 예외 처리기에서 예외를 catch하고 사용자 지정 오류 메시지를 반환하고 싶습니다. 어떻게해야합니까? 어떤 도움을 주셔서 감사합니다. 미리 감사드립니다. 당신은 AuthenticationEntryPoint을 구현하고 commence 메소드를 오버라이드 (override) 할을 처리 할 필요가,

+1

실제로 예외가 발생했는지 또는 제공자가 처음에 호출되고 있는지 확인 했습니까? – pvg

답변

1

GlobalExceptionHandler 컨트롤러의 예외 핸들러입니다,하지만 당신은 AuthenticationException를 핸들러하려는 경우 AuthenticationProvider는 필터에 아직도있다.

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

AuthenticationExceptionAccessDeniedException 이미 ExceptionTranslationFilter에 의해 처리되고있다. 당신은

(AccessDeniedException 처리) AuthenticationEntryPointAccessDeniedHandler를 주입 할 필요가 또는 당신은 필터에서 이러한 예외를 캐치 한 후 컨트롤러 예외 핸들러가있다 전에 인증 공급자라고 AuthenticationFailureHandler

0

AbstractAuthenticationProcessingFilter에서처럼, 파일러에서 처리 할 수 예외를 잡을 기회.

당신은 documentation에 설명 된대로 examples

동작을보고, 보안 필터 체인 수준에서 예외를 처리하는 AuthenticationFailureHandler을 재정의 할 수

필터는 각각의 인증 요청을 처리하기 위해 구성된 AuthenticationManager에 호출합니다. 성공적인 인증 또는 인증 실패 이후의 대상은 각각 AuthenticationSuccessHandler 및 AuthenticationFailureHandler 전략 인터페이스에 의해 제어됩니다. 이 필터는 @chaoluo가 이미 AuthenticationEntryPoint을 구현하고 commence 메소드를 오버라이드 (override) 할 필요가 말했듯이 당신이 행동을 완전히

0

을 사용자 정의 할 수 있도록 다음을 설정할 수 속성이 있습니다. 오류 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(); 
} 
관련 문제