spring security에서 담당하는 두 영역인 authentication과 authorization에 각각 매칭되는 두 예외가 있다.
authentication -> AuthenticationException
authorization -> AccessDeniedException
각각을 구현하고 상속하는 여러가지 예외들이 더 많이 존재한다.
나는 계정 탈퇴 페이지에서 비밀번호를 확인 받고, 비밀번호가 틀렸을 경우 AuthenticationException를 상속 받는 예외중 하나인 BadCredentialsException을 던지도록 했다.
@Component
@Slf4j
public class CustomAuthenticationFailureHandler implements AuthenticationFailureHandler {
@Override
public void onAuthenticationFailure(HttpServletRequest request, HttpServletResponse response, AuthenticationException exception) throws IOException, ServletException {
String errorType = "AuthenticationFailureType";
// BadCredentialsException
if(exception instanceof BadCredentialsException){
errorType = "password";
}
// UsernameNotFoundException
if(exception instanceof UsernameNotFoundException){
errorType = "username";
}
// redirect
response.sendRedirect(request.getRequestURI() + "?error=true&type=" + errorType);
}
}
위와 같이 구성하여, AuthenticationException인 exception의 타입이 BadCredentialsException인 경우 password라는 type 변수를 url쿼리에 전송해주도록했다.
이 핸들러를 bean으로 등록하고, Security Configuration에가서 다음과 같이 exceptionHandling을 설정해주면 된다.
http
.exceptionHandling(exception -> exception
.accessDeniedHandler(defaultAccessDeniedHandler)
.authenticationEntryPoint(customAuthenticationEntryPoint)
);
authorization 예외처리 설정 api는 이름이 직관적인데반해, authentication 관련 예외 처리 핸들러 세팅 api는 authenticationEntryPoint라는 이름을 가지고있어서 처음에 좀 헷갈렸다.
아마 대부분의 authentication 관한 예외가 로그인 과정에서 발생하기에, 이름을 이렇게 지은게 아닐까 싶다.