Token Provider에서 토큰의 서명, 토큰 자체의 문제에 대한 예외를 처리하거나, 토큰의 지원여부와 만료여부에 대한 예외도 처리했다.
그런데도 처리해야할게 남았다. 뭘까...?
생각해보면,우리가 보낸 예외처리에 대해 어떻게 반응해야 할지 처리를 안했다.
이전에 만들었던 validateToken부분에서는 모든 예외를 받아와 이를 로그로 출력시키는 과정을 만들어두었다.
그렇다면, 사용자에게 해당 예외에 대해 어떻게 처리할지 알아야 한다. (AuthenticationEntryPoint)
또한, 이 때는 토큰에 문제가 있을 경우에만 처리가 되었으며,
토큰에 문제가 없는데 토큰에 있는 사용자의 권한상 해당 요청을 할 수 없을 경우 이를 처리해주어야 한다. (예를 들면, 사용자가 관리자 페이지를 가면 곤란해진다. ) (AccessDeniedHandler)
괄호에 있는 해당 인터페이스들이 이런 역할을 맡아주긴 한다.
AccessDeniedHandler
이를 간단하게 정리해보자면, AuthenticationEntryPoint는 Authentication을 가져왔지만, 해당 인증을 가지고 요청 자체를 보낼 수 없는 경우이다.
AccessDeniedHandler는 Authentication(인증)은 되어있는 사용자이지만, 해당 요청에 대한 권한이 없는(즉, Authorized(권한있는) 사용자가 아니라는 뜻) 상태이다.
이렇기에, 인터페이스의 해당 메서드들을 Override, 인터페이스를 implements해서 커스텀으로 만들어줄 생각이다.
사실 해당 사용자들에게 보여줄 부분들은 단순하게 생각했다.
HTTP 에러코드를 찾아보았을 때, 인증에 대한 문제는 401, 권한에 대한 문제는 403으로 처리한다는 말을 듣고, 해당 예외만 처리하는 코드로 정리를 했다.
@Component
public class JwtAuthenticationEntryPoint implements AuthenticationEntryPoint {
@Override
public void commence(HttpServletRequest request,
HttpServletResponse response,
AuthenticationException authException) throws IOException {
response.sendError(401);
}
}
@Component
public class JwtAccessDenialHandler implements AccessDeniedHandler {
@Override
public void handle(HttpServletRequest request, HttpServletResponse response,
AccessDeniedException accessDeniedException) throws IOException{
response.sendError(403);
}
}
이런식으로 처리를 하려했는데, 생각해보면 좋지 않은 방식 같았다.
머리속에서 생각해보았을 때,
RuntimeException을 확장받아 TokenProvider에서 예외를 발생시킨다.
이를 AuthenticationEntryPoint가 받아 예외를 401, 403으로 처리해준다.
사용자가 이러한 응답을 받는다.
문제가 없는 듯 하지만, 만약 새로운 페이지를 만들어 사용할 때 이런 문제가 예기치 않게 발생할 수 있다.
그래서 로그를 추가하기로 했다.
@Component
@Slf4j
public class JwtAuthenticationEntryPoint implements AuthenticationEntryPoint {
@Override
public void commence(HttpServletRequest request,
HttpServletResponse response,
AuthenticationException authException) throws IOException {
LocalDateTime now = LocalDateTime.now();
log.error("time : " + now + "\nrequest" + request + "\nException" + authException.getMessage());
response.sendError(401);
}
}
@Component
@Slf4j
public class JwtAccessDenialHandler implements AccessDeniedHandler {
@Override
public void handle(HttpServletRequest request, HttpServletResponse response,
AccessDeniedException accessDeniedException) throws IOException{
LocalDateTime now = LocalDateTime.now();
log.error("time : " + now + "\nrequest" + request + "\nException" + accessDeniedException.getMessage());
response.sendError(403);
}
}
이렇게 로그를 위한 어노테이션과, 로그에 에러로 출력을 저장해주는 기능을 넣었다.
간단하게 예외에 대한 방식을 추가했다.
이를 쉽게 정리해보자면,
- JWT 인증, 권한에 대한 예외처리는 JWT에서 제공된다.
- 제공된 인터페이스를 주입받아 예외처리 클래스를 따로 만든다.
- 클래스에서 예외시 발생한 내용들을 로그로 처리해주고, 사용자에게 에러를 반환해준다.
이정도로 정리를 했다.
다음엔 토큰을 받아왔을 때, 여기에서 필요한 부분만 빼내는 필터와, 이러한 필터를 기존 시큐리티 필터 체인에 추가하는 과정을 만들어봐야겠다.
'스프링 공부 > 게시판 프로젝트 만들기' 카테고리의 다른 글
[스프링] 11. BaseEntity를 만들어보자. (0) | 2023.01.09 |
---|---|
[스프링] 10. JWT를 구현하기. 찐막: 필터만들기와 SecurityConfiguration에 JWT 추가하기 (0) | 2023.01.09 |
[스프링] 8. JWT를 구현하기. 1단계: 일단 JWT를 위한 토큰을 만들자. (2) (1) | 2023.01.06 |
[스프링] 7. JWT를 구현하기. 1단계: 일단 JWT를 위한 토큰을 만들자. (1) (0) | 2023.01.06 |
[스프링] 6. SecurityUtil 예외처리를 커스텀 해보자(부제: 2단계, 리스폰스를 이용해 예외처리하기) (0) | 2023.01.02 |