From 7b416538cdf834584c5164f633250e56c5a25a0a Mon Sep 17 00:00:00 2001 From: wlgns12370 Date: Wed, 13 Aug 2025 05:30:37 +0900 Subject: [PATCH 1/3] =?UTF-8?q?MOSU-344=20refactor:=20Controller=20?= =?UTF-8?q?=EC=A0=84=20=EC=97=90=EB=9F=AC=20=EC=B2=98=EB=A6=AC?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../global/filter/TokenExceptionFilter.java | 47 +++++++++++++++++-- 1 file changed, 43 insertions(+), 4 deletions(-) diff --git a/src/main/java/life/mosu/mosuserver/global/filter/TokenExceptionFilter.java b/src/main/java/life/mosu/mosuserver/global/filter/TokenExceptionFilter.java index 8b6911e1..7a3e38ee 100644 --- a/src/main/java/life/mosu/mosuserver/global/filter/TokenExceptionFilter.java +++ b/src/main/java/life/mosu/mosuserver/global/filter/TokenExceptionFilter.java @@ -1,12 +1,17 @@ package life.mosu.mosuserver.global.filter; +import com.fasterxml.jackson.databind.ObjectMapper; +import io.jsonwebtoken.ExpiredJwtException; import jakarta.servlet.FilterChain; import jakarta.servlet.ServletException; import jakarta.servlet.http.HttpServletRequest; import jakarta.servlet.http.HttpServletResponse; import java.io.IOException; import life.mosu.mosuserver.global.exception.CustomRuntimeException; +import life.mosu.mosuserver.global.exception.ErrorResponse; import lombok.RequiredArgsConstructor; +import org.springframework.http.HttpStatus; +import org.springframework.http.MediaType; import org.springframework.stereotype.Component; import org.springframework.web.filter.OncePerRequestFilter; @@ -14,6 +19,8 @@ @RequiredArgsConstructor public class TokenExceptionFilter extends OncePerRequestFilter { + private final ObjectMapper objectMapper; + @Override protected void doFilterInternal( final HttpServletRequest request, @@ -22,11 +29,43 @@ protected void doFilterInternal( ) throws ServletException, IOException { try { filterChain.doFilter(request, response); - } catch (CustomRuntimeException exception) { - response.setStatus(HttpServletResponse.SC_UNAUTHORIZED); - response.setContentType("application/json"); + } catch (CustomRuntimeException ex) { + + ErrorResponse errorResponse = ErrorResponse.builder() + .status(ex.getStatus().value()) + .message(ex.getMessage()) + .code(ex.getCode()) + .build(); + + response.setStatus(HttpStatus.UNAUTHORIZED.value()); + response.setContentType(MediaType.APPLICATION_JSON_VALUE); + response.setCharacterEncoding("UTF-8"); + + objectMapper.writeValue(response.getWriter(), errorResponse); + } catch (ExpiredJwtException ex) { + ErrorResponse errorResponse = ErrorResponse.builder() + .status(HttpStatus.NOT_ACCEPTABLE.value()) + .message("토큰이 만료되었습니다.") + .code("TOKEN_EXPIRED") + .build(); + + response.setStatus(HttpStatus.NOT_ACCEPTABLE.value()); + response.setContentType(MediaType.APPLICATION_JSON_VALUE); response.setCharacterEncoding("UTF-8"); - response.sendError(exception.getStatus().value(), exception.getMessage()); + + objectMapper.writeValue(response.getWriter(), errorResponse); + } catch (Exception ex) { + ErrorResponse errorResponse = ErrorResponse.builder() + .status(HttpStatus.INTERNAL_SERVER_ERROR.value()) + .message("서버 오류가 발생했습니다.") + .code("INTERNAL_SERVER_ERROR") + .build(); + + response.setStatus(HttpStatus.INTERNAL_SERVER_ERROR.value()); + response.setContentType(MediaType.APPLICATION_JSON_VALUE); + response.setCharacterEncoding("UTF-8"); + + objectMapper.writeValue(response.getWriter(), errorResponse); } } } \ No newline at end of file From 24ae78f40361fc74901d9efde0720ce78af52787 Mon Sep 17 00:00:00 2001 From: wlgns12370 Date: Wed, 13 Aug 2025 05:49:14 +0900 Subject: [PATCH 2/3] =?UTF-8?q?MOSU-344=20feat:=20=ED=86=A0=ED=81=B0=20?= =?UTF-8?q?=EB=A7=8C=EB=A3=8C=20=EC=98=88=EC=99=B8=20catch?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../mosu/mosuserver/global/filter/TokenFilter.java | 10 +++++++--- 1 file changed, 7 insertions(+), 3 deletions(-) diff --git a/src/main/java/life/mosu/mosuserver/global/filter/TokenFilter.java b/src/main/java/life/mosu/mosuserver/global/filter/TokenFilter.java index 1ff63eb9..735fa7f8 100644 --- a/src/main/java/life/mosu/mosuserver/global/filter/TokenFilter.java +++ b/src/main/java/life/mosu/mosuserver/global/filter/TokenFilter.java @@ -1,5 +1,6 @@ package life.mosu.mosuserver.global.filter; +import io.jsonwebtoken.ExpiredJwtException; import jakarta.servlet.FilterChain; import jakarta.servlet.ServletException; import jakarta.servlet.http.HttpServletRequest; @@ -105,9 +106,12 @@ protected void doFilterInternal( try { setAuthentication(accessToken); + } catch (ExpiredJwtException e) { + log.error("액세스 토큰 만료: {}", e.getMessage()); + throw e; } catch (CustomRuntimeException e) { - log.error("액세스 토큰 인증 실패: {}", e.getMessage()); - throw new CustomRuntimeException(ErrorCode.INVALID_TOKEN); + log.error("유효하지 않은 토큰 인증 실패: {}", e.getMessage()); + throw e; } catch (Exception e) { log.error("액세스 토큰 인증 실패: {}", e.getMessage()); throw new RuntimeException("액세스 토큰 인증 중 예외 발생", e); @@ -120,7 +124,7 @@ private void reissueToken(HttpServletRequest request, HttpServletResponse respon throws IOException { final TokenCookies tokenCookies = tokenResolver.resolveTokens(request); if (!tokenCookies.availableReissue()) { - throw new CustomRuntimeException(ErrorCode.EXPIRED_REFRESH_TOKEN); + throw new CustomRuntimeException(ErrorCode.NOT_FOUND_TOKEN); } Token newToken = authTokenManager.reissueToken(tokenCookies); From 323484efa944bb0be93e7cbd7e75bfbba9fc9fdf Mon Sep 17 00:00:00 2001 From: wlgns12370 Date: Wed, 13 Aug 2025 05:52:13 +0900 Subject: [PATCH 3/3] =?UTF-8?q?MOSU-344=20feat:=20JwtToken=20=EC=97=90?= =?UTF-8?q?=EB=9F=AC=20=ED=95=B8=EB=93=A4=EB=A7=81?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../application/auth/provider/JwtTokenProvider.java | 8 +++++++- 1 file changed, 7 insertions(+), 1 deletion(-) diff --git a/src/main/java/life/mosu/mosuserver/application/auth/provider/JwtTokenProvider.java b/src/main/java/life/mosu/mosuserver/application/auth/provider/JwtTokenProvider.java index acc26266..b51bdb06 100644 --- a/src/main/java/life/mosu/mosuserver/application/auth/provider/JwtTokenProvider.java +++ b/src/main/java/life/mosu/mosuserver/application/auth/provider/JwtTokenProvider.java @@ -106,9 +106,15 @@ protected Claims validateAndParseToken(final String token) { } if (claims.getExpiration().toInstant().isBefore(new Date().toInstant())) { - throw new CustomRuntimeException(ErrorCode.EXPIRED_TOKEN); + throw new ExpiredJwtException( + null, + claims, + "JWT 토큰이 만료되었습니다." + ); } return claims; + } catch (ExpiredJwtException exception) { + throw exception; } catch (JwtException | IllegalArgumentException exception) { throw new CustomRuntimeException(ErrorCode.INVALID_TOKEN_TYPE); }