앞선 페이지에서 인증과 인가 과정의 예외 상황에서 AccessDeniedHandler, AuthenticationEntryPoint로 에외 전달
AccessDeniedHandler 인터페이스 구현체 클래스 생성
@Component
public class CustomAccessDeniedHandler implements AccessDeniedHandler {
private final Logger LOGGER = LoggerFactory.getLogger(CustomAccessDeniedHandler.class);
@Override
public void handle(HttpServletRequest request, HttpServletResponse response, AccessDeniedException accessDeniedException) throws IOException, ServletException {
LOGGER.info("[handle] 접근이 막혔을 경우 경로 리다이렉트");
response.sendRedirect("/sign-api/exception");
}
}
AccessDeniedException
은 엑세스 권한이 없는 리소스에 접근 시 발생하는 예외
-> 이를 처리하기 위해 AccessDeniedHandler 인터페이스가 사용되며, SecurityConfiguration에도 exceptionHandling() 메서드를 통해 추가
handle() 메서드를 오버라이딩 하였음
response에서 리다이렉트하는 sendRedirect()메서드를 활용하는 방식으로 구현
-> 접근이 막혔을 경우 경로 리다이렉트가 출력된 후 다른 스레드에서 동작하게 됨
인증이 실패한 상황을 처리하는 AuthenticationEntryPoint 인터페이스를 구현한 CustomAuthenticationEntryPoint 클래스
@Component
public class CustomAuthenticationEntryPoint implements AuthenticationEntryPoint {
private final Logger LOGGER = LoggerFactory.getLogger(CustomAuthenticationEntryPoint.class)
@Override
public void commence(HttpServletRequest request, HttpServletResponse response, AuthenticationException authException) throws IOException, ServletException {
ObjectMapper objectMapper = new ObjectMapper();
LOGGER.info("[commence] 인증 실패로 response.sendError 발생");
EntryPointErrorResponse entryPointErrorResponse = new EntryPointErrorResponse();
entryPointErrorResponse.setMsg("인증이 실패하였습니다");
response.setStatus(401);
response.setContentType("application/json");
response.setCharacterEncoding("utf-8");
response.getWriter().write(objectMapper.writeValueAsString(entryPointErrorResponse));
}
}
EntryPointErrorResponse
@Data
@NoArgsConstructor
@AllArgsConstructor
@ToString
public class EntryPointErrorResponse {
private String msg;
}
구조가 앞선 AccessDeniedHandler와 크게 다르지 않으며, commence() 오버라이딩
예외 처리를 위해 리다이렉트가 아니라 직접 Response를 생성해서 클라이언트에게 응답하는 방식으로 구현돼 있음
컨트롤러에서는 응답을 위한 설정들이 자동으로 구현되기에 별도의 작업을 하지 않았지만 여기서는 응답값을 설정해 주어야 함
-> 메세지 담기 위해 EntryPointErrorResponse 객체 사용해 메세지 설정, response에 상태 코드와 콘텐츠 타입을 설정한 후 ObjectMapper를 사용해 EntryPointErrorResponse 객체를 바디 값으로 파싱
궅이 메세지 설정이 필요없다면
@Override
public void commence(HttpServletRequest request, HttpServletResponse response
, AuthenticationException ex) throws IOExcpetion{
reponse.sendError(HttpServletResponse.SC_UNAUTHORIZED);
}