RestAuthenticationSuccessHandler
RestAuthenticationSuccessHandler는 Spring Security에서 인증 성공 후 처리를 담당하는 인증 성공 핸들러다. 주로 REST API에서 인증이 성공한 후에 추가적인 응답을 처리하거나, 커스텀 로직을 적용할 수 있도록 구현된다. REST API 환경에서는 페이지 리다이렉션 대신 JSON 응답을 반환하는 것이 일반적이므로, 이를 적절하게 처리하는 역할을 한다.
1. AuthenticationSuccessHandler란?
- AuthenticationSuccessHandler는 사용자가 인증에 성공했을 때 호출되는 인터페이스로, 인증 성공 후의 동작을 정의한다.
- 주로 페이지 기반 웹 애플리케이션에서는 인증 성공 시 사용자를 특정 페이지로 리다이렉션하는 역할을 하지만, REST API에서는 JSON 응답을 통해 인증 성공 결과를 반환하는 방식이 더 일반적이다.
2. RestAuthenticationSuccessHandler의 역할
- REST API에서 인증이 성공하면, 리다이렉션 대신에 JSON 응답이나 다른 형식의 응답을 통해 클라이언트에게 인증 결과를 전달한다.
- 주로 **상태 코드 200 (OK)**와 함께 인증된 사용자 정보나 토큰을 반환할 수 있다.
- 성공한 인증 정보를 바탕으로, 추가적인 처리가 필요하면 그 작업을 수행한다. 예를 들어, JWT 토큰 생성 또는 사용자 세션 처리를 할 수 있다.
3. RestAuthenticationSuccessHandler의 기본 구조
RestAuthenticationSuccessHandler는 SimpleUrlAuthenticationSuccessHandler를 상속받아 구현하는 경우가 많으며, onAuthenticationSuccess 메서드를 오버라이드하여 커스텀 처리 로직을 작성할 수 있다.
코드 설명
@Component("restSuccessHandler")
// 이 클래스가 Spring Security의 AuthenticationSuccessHandler 빈으로 등록됨을 나타냄.
// 빈 이름은 "restSuccessHandler"로 설정되어 있으며, REST API에서 인증 성공 시 이 핸들러가 호출된다.
public class RestAuthenticationSuccessHandler implements AuthenticationSuccessHandler {
@Override
public void onAuthenticationSuccess(HttpServletRequest request, HttpServletResponse response, Authentication authentication) throws IOException {
ObjectMapper mapper = new ObjectMapper();
// Jackson의 ObjectMapper를 사용하여 Java 객체를 JSON으로 변환.
AccountDto accountDto = (AccountDto) authentication.getPrincipal();
// 인증된 사용자 정보를 Authentication 객체에서 가져옴. 이 경우, 사용자 정보는 AccountDto 타입으로 캐스팅됨.
// AccountDto는 인증된 사용자 정보를 담고 있는 DTO(Data Transfer Object).
response.setStatus(HttpStatus.OK.value());
// HTTP 응답 상태 코드를 200 (OK)로 설정하여 인증이 성공했음을 나타냄.
response.setContentType(MediaType.APPLICATION_JSON_VALUE);
// 응답의 Content-Type을 "application/json"으로 설정하여 클라이언트에게 JSON 형식으로 데이터를 전달할 것임을 알림.
accountDto.setPassword(null);
// 비밀번호 정보를 보안상 이유로 응답에서 제거. 비밀번호는 인증이 성공한 후에는 클라이언트에게 노출되지 않도록 함.
mapper.writeValue(response.getWriter(), accountDto);
// AccountDto 객체를 JSON 형식으로 변환한 후, 응답 본문에 작성하여 클라이언트에게 전달.
// 클라이언트는 인증된 사용자 정보를 JSON 형식으로 응답받게 됨.
clearAuthenticationAttributes(request);
// 인증 과정 중에 발생한 잠재적인 인증 예외 정보를 세션에서 제거하여, 이후 요청에 영향을 미치지 않도록 함.
}
protected final void clearAuthenticationAttributes(HttpServletRequest request) {
HttpSession session = request.getSession(false);
// 현재 세션을 가져오되, 세션이 존재하지 않으면 null을 반환. (세션을 새로 생성하지 않음)
if (session == null) {
return;
}
// 세션이 없으면 아무 작업도 하지 않고 반환.
session.removeAttribute(WebAttributes.AUTHENTICATION_EXCEPTION);
// 세션에서 AUTHENTICATION_EXCEPTION 속성을 제거하여, 인증 예외 정보를 삭제.
// 이는 인증 성공 후 이전의 실패 정보가 남아있지 않도록 하기 위한 처리.
}
}
RestAuthenticationFailureHandler
1. RestAuthenticationFailureHandler의 역할
- REST API 환경에서 인증이 실패하면 상태 코드 401 (Unauthorized) 또는 400 (Bad Request) 등의 상태 코드와 함께 JSON 형식의 에러 메시지를 반환하여 클라이언트에게 실패 원인을 전달한다.
- 인증 실패의 원인은 보통 잘못된 사용자 이름 또는 비밀번호, 계정 비활성화, 계정 잠금 등의 문제로 인해 발생할 수 있다.
2. RestAuthenticationFailureHandler의 동작 원리
- 인증 실패 시 호출
- 사용자가 잘못된 자격 증명(사용자 이름/비밀번호)을 입력하거나, 계정이 비활성화된 상태에서 로그인하려고 시도하면 Spring Security는 이 핸들러의 onAuthenticationFailure 메서드를 호출한다.
- HTTP 응답 상태 코드 설정
- 응답 상태 코드를 401 (Unauthorized)로 설정하여, 클라이언트에게 인증 실패를 알린다. 이 상태 코드는 인증이 필요한 요청에서 자격 증명이 잘못되었을 때 반환된다.
- JSON 형식으로 에러 메시지 반환
- 응답의 Content-Type을 application/json으로 설정하여 클라이언트에게 JSON 응답임을 명확히 한다.
- 인증 실패의 원인(예: 비밀번호 오류, 계정 잠금 등)을 나타내는 메시지를 JSON 형식으로 클라이언트에게 전달한다.
- 추가적인 실패 정보 설정
- 실패 응답에 포함될 데이터를 설정한다. 일반적으로 타임스탬프, 상태 코드, 그리고 실패 원인(예외 메시지)이 포함된다. 예외 메시지는 AuthenticationException에서 가져와서 실패 원인에 따라 다르게 처리할 수 있다.
- JSON 응답 전송
- ObjectMapper를 사용하여 설정된 데이터를 JSON 형식으로 변환하고, 이를 응답 본문에 기록하여 클라이언트에게 전송한다. 클라이언트는 이 데이터를 받아서 인증 실패에 대한 상세 정보를 확인할 수 있다.
코드 설명
@Component("restFailureHandler")
// 이 클래스가 Spring Security의 AuthenticationFailureHandler 빈으로 등록됨을 나타냄.
// 빈 이름은 "restFailureHandler"로 설정되어 있으며, REST API에서 인증 실패 시 호출되는 핸들러 역할을 함.
public class RestAuthenticationFailureHandler implements AuthenticationFailureHandler {
@Override
public void onAuthenticationFailure(HttpServletRequest request, HttpServletResponse response, AuthenticationException exception) throws IOException {
ObjectMapper mapper = new ObjectMapper();
// Jackson의 ObjectMapper를 사용해 Java 객체를 JSON 형식으로 변환할 준비. 실패 메시지를 JSON으로 변환하여 응답할 때 사용됨.
response.setStatus(HttpStatus.UNAUTHORIZED.value());
// 응답 상태 코드를 401 Unauthorized로 설정. 이는 인증이 실패했음을 나타내는 표준 HTTP 상태 코드임.
response.setContentType(MediaType.APPLICATION_JSON_VALUE);
// 응답의 Content-Type을 application/json으로 설정하여 클라이언트에게 JSON 형식의 데이터를 반환할 것임을 명시.
if (exception instanceof BadCredentialsException) {
// 발생한 예외가 BadCredentialsException(잘못된 사용자 이름 또는 비밀번호)인 경우.
mapper.writeValue(response.getWriter(), "Invalid username or password");
// "Invalid username or password"라는 메시지를 JSON 형식으로 변환하여 응답 본문에 작성.
}
mapper.writeValue(response.getWriter(), "Authentication failed");
// 그 외의 경우(다른 유형의 인증 실패)에는 "Authentication failed" 메시지를 응답 본문에 작성.
// 단, 이전에 메시지를 기록한 경우에도 이 줄이 실행되므로 두 번의 응답이 기록됨. (버그 가능성 있음)
}
}