Spring Boot/Security

AuthenticationEntryPoint & AccessDeniedHandler

최-코드 2024. 10. 6. 14:21

배경지식 :

  • ExceptionHandlingConfigurer라는 클래스가 EntryPoint와 DeninedHandler 대한 구현체를 받아 defaultEntryPointMappings와, defulatDeniedHandlerMappings라는 Map객체에 저장한다.
  • 기본적으로 FormLogin과 HttpBasic인증 방식에 대한 defulat한 예외 설정이 존재하며, 커스텀한 것이 존재하면 이것이 우선적으로 실행된다.
  • SecurityFilterChain에는 ExceptionTranslationFilter가 존재하는데, 이는 Filter Chain 내부에서 발생하는 AccessDeniedException과 AuthenticationException의 처리를 담당한다.
  • 만약 ExceptionTranslationFilter AuthenticationException을 감지했다면 authenticationEntryPoint를 실행한다. 이것을 통해서 AbstractSecurityInterceptor의 서브클래스에서 발생하는 인증 실패를 공동으로 처리할 수 있다.
  • 만약 ExceptionTranslationFilter AccessDeniedException을 감지했다면 해당 사용자가 익명 사용자 인지의 여부를 판별하고 만약 익명 사용자일 경우 동일하게 authenticationEntryPoint을 실행한다. 만약 익명 사용자가 아닐 경우엔  AccessDeniedHandler을 위임한다.
  • 즉, ExceptionTranslationFilter는 ExceptionHandlingConfigurer를 참고해서 감지한 것에 대한 예외를 처리한다.
AuthenticationException : 인증 과정에서 에러가 생겼을 경우 발생하는 예외
AccessDeniedException : 인가 과정에서 에러가 생겼을 경우 발생하는 예외(-> role값이 맞지 않을 때)

 

간단 예제

public class CustomAuthenticationEntryPoint implements AuthenticationEntryPoint {

    @Override
    public void commence(HttpServletRequest request, HttpServletResponse response, AuthenticationException authException) throws IOException, ServletException {
        response.setStatus(HttpStatus.UNAUTHORIZED.value());
        response.getWriter().write(authException.getMessage());
    }
}

 

public class CustomAccessDeniedHandler implements AccessDeniedHandler {

    @Override
    public void handle(HttpServletRequest request, HttpServletResponse response, AccessDeniedException accessDeniedException) throws IOException, ServletException {
    	response.setStatus(HttpStatus.FORBIDDEN.value());
        response.getWriter().write(accessDeniedException.getMessage());
    }
}