1. 개요
어떤 응답에 대해서 세 번씩 요청이 오는 경우가 생겼습니다. 이를 어떻게 해결했는지 간단하게 알아보고자 합니다.
2. doFilter()
@RequiredArgsConstructor
public class JwtAuthenticationFilter extends OncePerRequestFilter {
private final JwtTokenProvider jwtTokenProvider;
private final UserRepository userRepository;
@Override
protected void doFilterInternal(HttpServletRequest request, HttpServletResponse response,
FilterChain filterChain) throws ServletException, IOException {
/**
* OAuth 토큰을 추출합니다. 구별을 위해 OAuth prefix를 사용합니다.
*/ String oAuthToken = jwtTokenProvider.extractOAuthToken(request)
.orElse(null);
/**
* OAuth Token이 null이 아니라면 로그인 요청이니 다음 필터로 바로 넘어갑니다.
*/
if (oAuthToken != null) {
// 1
filterChain.doFilter(request, response);
}
/**
* 사용자 요청 헤더에서 RefreshToken을 추출합니다.
* RefreshToken이 없거나 유효하지 않다면 null을 반환합니다.
* 사용자 요청 헤더에 RefreshToken이 있는 경우는 AccessToken이 만료되었을 때입니다.
* AccessToken이 만료되었다면 (403 ERROR) 후 클라이언트가 다시 요청합니다.
*/
String refreshToken = jwtTokenProvider.extractRefreshToken(request)
.filter(jwtTokenProvider::isTokenValid)
.orElse(null);
if (refreshToken != null) {
verifyRefreshTokenAndReIssueAccessToken(response, refreshToken);
}
if (refreshToken == null) {
verifyAccessTokenAndSaveAuthentication(request, response, filterChain);
}
// 2
filterChain.doFilter(request, response);
}
private void verifyAccessTokenAndSaveAuthentication(HttpServletRequest request,
HttpServletResponse response, FilterChain filterChain)
throws ServletException, IOException {
jwtTokenProvider.extractAccessToken(request)
.filter(jwtTokenProvider::isTokenValid)
.ifPresent(accessToken -> jwtTokenProvider.getSubject(accessToken)
.ifPresent(email -> userRepository.findByEmail(email)
.ifPresent(this::saveAuthentication)));
// 3
doFilter(request,response);
}
SQL
복사
최대한 많은 부분을 덜어놨는데요, 이 코드의 문제는 doFilter(request, response)가 많다는 것입니다. 사실 많은 것은 문제가 안됩니다. 중요한건 return; 즉, 메소드를 끝내지 않기 때문에 스택 처럼 doFilter(request, response)가 쌓여서 모두 다 실행된다는 점입니다.
이를 해결하려면 적절한 구간에 return; 코드를 삽입해서 메소드를 끝내주어야 합니다.
예를 들어. OAuth 로그인을 하는 과정임이 드러났다면
if (oAuthToken != null) {
filterChain.doFilter(request, response);
return; // return 문 삽입
}
Java
복사
다음과 같이 진행해주어야 합니다.