티스토리 뷰
[Spring Security] HandlerExceptionResolver 를 사용한 토큰 필터에서의 예외 처리
Nickolodeon 2022. 12. 26. 17:03Configuration 클래스에서 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
'Web Framework' 카테고리의 다른 글
[Spring Boot] required a bean of type '...' that could not be found 에러 (0) | 2023.08.29 |
---|---|
[Spring Security] 경로에 @PathVariable 을 포함하는 API 를 인증 없이도 호출하도록 설정하기 (5) | 2023.01.05 |
[Spring Security] 토큰 발행 후 API에 토큰 인증 절차 추가하기 (2) | 2022.12.06 |
[Spring Security] Spring Security 적용 후 컨트롤러 테스트 (0) | 2022.12.02 |
[Spring] ResponseEntity (0) | 2022.11.28 |
- Total
- Today
- Yesterday
- DTO
- 역직렬화
- 지연 로딩
- spring
- Java Data Types
- ci/cd
- 깃랩
- DeSerialization
- google cloud
- LazyInitializationException
- Spring Boot
- N+1
- docker
- Firebase
- JOIN FETCH
- 실시간데이터
- 프로그래머스
- FCM
- JPA
- gitlab
- Jackson
- JPQL
- 코테
- @RequestBody
- 인증/인가
- json web token
- 기지국 설치
- 도커
- 알고리즘
- 가상 서버
일 | 월 | 화 | 수 | 목 | 금 | 토 |
---|---|---|---|---|---|---|
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 |