티스토리 뷰

Configuration 클래스에서 HandlerExceptionResolver 주입하기

기존 SecurityConfig 클래스에 다음 두 줄을 추가한다:

private final HandlerExceptionResolver exceptionResolver;

public SecurityConfig(@Qualifier("handlerExceptionResolver") HandlerExceptionResolver exceptionResolver) {
    this.exceptionResolver = exceptionResolver;
}

그리고 기존에 JwtAuthenticationFilter 는 매개 변수로 비밀 키만 받고 있었는데, 필드 변수로 생성된 exceptionResolver 도 받도록 변경한다.

 

보안 필터체인은 아래처럼 Jwt 필터에서 비밀 키 말고도 하나의 매개변수를 더 가지도록 변경되었다:

.addFilterBefore(new JwtAuthenticationFilter(secretKey, exceptionResolver),
               				 UsernamePasswordAuthenticationFilter.class)
.build();

따라서 JwtAuthenticationFilter 의 필드 변수들도 아래와 같이 변경되었다:

String secretKey;

private final HandlerExceptionResolver exceptionResolver;

이제 HandlerExceptionResolver 객체는 토큰 필터 내에서 유효하지 않은 토큰에 대한 예외 처리를 담당한다:

try {
    if (TokenUtils.isExpired(token, secretKey)) {
        filterChain.doFilter(request, response);
        return;
    }

    String userId = TokenUtils.getUserId(token, secretKey);

    SecurityContextHolder.getContext().setAuthentication(TokenUtils.getAuthentication(userId));
    filterChain.doFilter(request, response);
} catch (ExpiredJwtException e) {
    exceptionResolver.resolveException(request, response, null, e);
}

유효하지 않은 토큰을 찾는 시점부터 서블릿을 실행하는 filterChain.doFilter 메서드 실행까지를 try catch 블록에 넣었다.

 

그리고 @ControllerAdvice 가 붙은 클래스에서 ExpiredJwtException 을 원하는 방식으로 처리하도록 메서드를 추가한다:

@ResponseBody
@ExceptionHandler(ExpiredJwtException.class)
public ResponseEntity<?> expiredTokenExceptionHandler(ExpiredJwtException exception) {
    ErrorResponse errorResponse = new ErrorResponse(ErrorCode.INVALID_PERMISSION, "사용자가 권한이 없습니다.");
    return ResponseEntity.status(errorResponse.getErrorCode().getHttpStatus())
            .body(Response.fail(errorResponse));
}

이제 Swagger 에서 유효하지 않은 토큰으로 로그인 된 상황에서 포스트를 등록하려 하면 JSON 형태 데이터를 반환한다:

문제는 회원 가입도 유효한 토큰이 있어야만 가능하다는 것이었다. 보안 필터 체인에서, 특정 API 에 대해서만 토큰 필터를 적용하도록 바꾸어주었다:

.authorizeRequests()
.antMatchers(HttpMethod.POST, "/api/v1/users/join", "/api/v1/users/login")
.permitAll()
.and()
.antMatcher("/api/v1/posts/**")
.authorizeRequests()
.anyRequest().authenticated()
.and()
.addFilterBefore(new JwtAuthenticationFilter(secretKey, exceptionResolver), UsernamePasswordAuthenticationFilter.class)
.build();

회원가입과 로그인 API 에는 토큰 필터가 적용되지 않는다. 권한을 요구할 때 사용되는 메서드는 antMatchers 가 아닌 antMatcher 인 것에 유의하자.

 

출처

https://medium.com/@mypascal2000/custom-handling-of-invalid-jwt-in-spring-boot-f66e60d59230

 

Custom Handling of Invalid JWT in Spring Boot

Handling exceptions is usually simple but every once a while, it proves itself as a topic that cannot be taken easily.

medium.com

https://stackoverflow.com/questions/36795894/how-to-apply-spring-security-filter-only-on-secured-endpoints

 

How to apply Spring Security filter only on secured endpoints?

I have the following Spring Security configuration: httpSecurity .csrf().disable() .exceptionHandling() .authenticationEntryPoint(unauthorizedHandler) .and()...

stackoverflow.com

 

공지사항
최근에 올라온 글
최근에 달린 댓글
Total
Today
Yesterday
링크
«   2025/02   »
1
2 3 4 5 6 7 8
9 10 11 12 13 14 15
16 17 18 19 20 21 22
23 24 25 26 27 28
글 보관함