쌓고 쌓다
Spring Security 인증/인가 예외 JSON 처리 본문
시큐리티 설정을 통해 인증, 인가 설정을 할 수 있다.
이제 이 인증, 인가에 실패했을 경우에 JSON 예외 응답을 보내보자.
SecurityConfig.java
http.exceptionHandling(e -> e
.authenticationEntryPoint(new JwtAuthenticationEntryPoint())
.accessDeniedHandler(new JwtAccessDenyHandler()));
exceptionHandling을 통해 예외를 처리할 로직은 시큐리티에 등록할 수 있다.
인증 예외는 AuthenticationEntryPoint 인터페이스를 구현하여 등록할 수 있고
인가 예외는 AccessDeniedHandler 인터페이스를 구현하여 등록할 수 있다.
먼저 Enum 타입으로 작성해둔 예외 종류와 메시지를 보자.
ErrorCode
import lombok.Getter;
import org.springframework.http.HttpStatus;
@Getter
public enum ErrorCode {
UNAUTHORIZED_CLIENT(HttpStatus.BAD_REQUEST, "접근 토큰이 없습니다."),
FORBIDDEN_CLIENT(HttpStatus.FORBIDDEN, "접근 권한이 없습니다."),
EXPIRED_TOKEN(HttpStatus.UNAUTHORIZED, "만료된 토큰입니다."),
JWT_DECODE_FAIL(HttpStatus.UNAUTHORIZED, "올바른 토큰이 필요합니다."),
JWT_SIGNATURE_FAIL(HttpStatus.UNAUTHORIZED, "올바른 토큰이 필요합니다.");
private HttpStatus httpStatus;
private String message;
ErrorCode(HttpStatus httpStatus, String message) {
this.httpStatus = httpStatus;
this.message = message;
}
}
ErrorResponse
import com.example.spotserver.exception.ErrorCode;
import lombok.Data;
import lombok.NoArgsConstructor;
@Data
@NoArgsConstructor
public class ErrorResponse {
private String errorCode;
private String message;
public ErrorResponse(ErrorCode errorCode) {
this.errorCode = errorCode.name();
this.message = errorCode.getMessage();
}
}
ErrorCode를 통해 에러 응답을 설정하여 응답으로 보낼 클래스이다.
JwtAccessDenyHandler (AccessDeniedHandler 구현체)
public class JwtAccessDenyHandler implements AccessDeniedHandler {
@Override
public void handle(HttpServletRequest request, HttpServletResponse response, AccessDeniedException accessDeniedException) throws IOException, ServletException {
ErrorResponse errorResponse = new ErrorResponse(ErrorCode.FORBIDDEN_CLIENT);
ObjectMapper objectMapper = new ObjectMapper();
String jsonErrorResponse = objectMapper.writeValueAsString(errorResponse);
response.setStatus(HttpStatus.FORBIDDEN.value());
response.setCharacterEncoding("utf-8");
response.setContentType(MediaType.APPLICATION_JSON_VALUE); // application/json
response.getWriter().write(jsonErrorResponse);
}
}
- handle() : 예외 발생시 처리할 로직이다.
- ObjectMapper : 객체를 JSON 형태로 바꿔 응답을 보내기위해 writeValueAsString을 사용한다.
- setStatus : HTTP 상태 코드 설정
- setCharacterEncoding : 한글이 깨져서 응답이 나갈 수 있다. 문자열 인코딩을 설정해주자.
JwtAuthenticationEntryPoint (AuthenticationEntryPoint 구현체)
import com.example.spotserver.domain.ErrorResponse;
import com.example.spotserver.exception.ErrorCode;
import com.fasterxml.jackson.databind.ObjectMapper;
import jakarta.servlet.ServletException;
import jakarta.servlet.http.HttpServletRequest;
import jakarta.servlet.http.HttpServletResponse;
import org.springframework.http.HttpStatus;
import org.springframework.http.MediaType;
import org.springframework.http.ResponseEntity;
import org.springframework.security.core.AuthenticationException;
import org.springframework.security.web.AuthenticationEntryPoint;
import org.springframework.web.bind.annotation.ExceptionHandler;
import java.io.IOException;
public class JwtAuthenticationEntryPoint implements AuthenticationEntryPoint {
@Override
public void commence(HttpServletRequest request, HttpServletResponse response, AuthenticationException authException) throws IOException, ServletException {
ErrorResponse errorResponse = new ErrorResponse(ErrorCode.UNAUTHORIZED_CLIENT);
ObjectMapper objectMapper = new ObjectMapper();
String jsonErrorResponse = objectMapper.writeValueAsString(errorResponse);
response.setStatus(HttpStatus.BAD_REQUEST.value());
response.setCharacterEncoding("utf-8");
response.setContentType(MediaType.APPLICATION_JSON_VALUE); // application/json
response.getWriter().write(jsonErrorResponse);
}
}
이제 인증/인가 예외 발생시 다음과 같이 JSON 응답을 줄 수 있다.
JWT 토큰과 관련된 예외는 필터를 걸고 Authorization 헤더가 존재하면 검증하는 로직에
다음과 같이 예외를 잡고 처리할 수 있다.
'프로그래밍 > spring' 카테고리의 다른 글
@BeforeAll, @AfterAll non-static 메서드로 호출하는법 (0) | 2024.01.26 |
---|---|
consumes, produces와 Content-Type 예외 처리 방법 (1) | 2024.01.25 |
Enum 타입으로 에러 메시지 및 응답 관리하기 (0) | 2024.01.24 |
REST API에서 DTO 유효성 검사와 예외 처리 응답 방법 (1) | 2024.01.22 |
Entity와 DTO의 분리 필요성 및 방법 (0) | 2024.01.22 |
Comments