Skip to content

Commit d7dc1e1

Browse files
authored
Merge pull request #72 from Nexters/feature/token-filter-entry-point
fix: 인증 예외처리 방식 변경
2 parents 871a071 + 2d8f9f9 commit d7dc1e1

File tree

4 files changed

+70
-22
lines changed

4 files changed

+70
-22
lines changed

src/main/java/com/climbup/climbup/auth/filter/JwtAuthenticationFilter.java

Lines changed: 11 additions & 21 deletions
Original file line numberDiff line numberDiff line change
@@ -39,29 +39,20 @@ protected void doFilterInternal(HttpServletRequest request,
3939
HttpServletResponse response,
4040
FilterChain filterChain) throws ServletException, IOException {
4141

42-
try {
43-
String token = extractTokenFromRequest(request);
44-
45-
if (StringUtils.hasText(token) && jwtUtil.isTokenValid(token)) {
46-
if (!jwtUtil.isAccessToken(token)) {
47-
log.debug("Access Token이 아닌 토큰으로 인증 시도: {}", jwtUtil.getTokenType(token));
48-
SecurityContextHolder.clearContext();
49-
} else {
42+
String token = extractTokenFromRequest(request);
43+
44+
if (StringUtils.hasText(token)) {
45+
try {
46+
if (jwtUtil.isTokenValid(token) && jwtUtil.isAccessToken(token)) {
5047
authenticateUser(request, token);
5148
}
49+
} catch (TokenExpiredException | InvalidTokenException e) {
50+
log.debug("토큰 검증 실패: {}", e.getMessage());
51+
} catch (UserNotFoundException e) {
52+
log.warn("토큰은 유효하지만 사용자를 찾을 수 없음: {}", e.getMessage());
53+
} catch (Exception e) {
54+
log.error("JWT 인증 처리 중 예상치 못한 오류 발생: {}", e.getClass().getSimpleName(), e);
5255
}
53-
} catch (InvalidTokenException e) {
54-
log.debug("유효하지 않은 토큰으로 인한 인증 실패: {}", e.getMessage());
55-
SecurityContextHolder.clearContext();
56-
} catch (TokenExpiredException e) {
57-
log.debug("만료된 토큰으로 인한 인증 실패: {}", e.getMessage());
58-
SecurityContextHolder.clearContext();
59-
} catch (UserNotFoundException e) {
60-
log.warn("토큰은 유효하지만 사용자를 찾을 수 없음: {}", e.getMessage());
61-
SecurityContextHolder.clearContext();
62-
} catch (Exception e) {
63-
log.error("JWT 인증 처리 중 예상치 못한 오류 발생: {}", e.getClass().getSimpleName(), e);
64-
SecurityContextHolder.clearContext();
6556
}
6657

6758
filterChain.doFilter(request, response);
@@ -116,7 +107,6 @@ private String extractTokenFromRequest(HttpServletRequest request) {
116107
protected boolean shouldNotFilter(HttpServletRequest request) throws ServletException {
117108
String path = request.getRequestURI();
118109

119-
// 정적 리소스나 공개 API는 검증하지 않음
120110
return path.startsWith("/css/") ||
121111
path.startsWith("/js/") ||
122112
path.startsWith("/images/") ||
Lines changed: 36 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,36 @@
1+
package com.climbup.climbup.auth.handler;
2+
3+
import com.climbup.climbup.common.dto.ErrorResponse;
4+
import com.climbup.climbup.common.exception.ErrorCode;
5+
import com.fasterxml.jackson.databind.ObjectMapper;
6+
import jakarta.servlet.http.HttpServletRequest;
7+
import jakarta.servlet.http.HttpServletResponse;
8+
import lombok.RequiredArgsConstructor;
9+
import lombok.extern.slf4j.Slf4j;
10+
import org.springframework.http.MediaType;
11+
import org.springframework.security.core.AuthenticationException;
12+
import org.springframework.security.web.AuthenticationEntryPoint;
13+
import org.springframework.stereotype.Component;
14+
15+
import java.io.IOException;
16+
17+
@Component
18+
@RequiredArgsConstructor
19+
public class CustomAuthenticationEntryPoint implements AuthenticationEntryPoint {
20+
21+
private final ObjectMapper objectMapper;
22+
23+
@Override
24+
public void commence(HttpServletRequest request,
25+
HttpServletResponse response,
26+
AuthenticationException authException) throws IOException {
27+
28+
response.setStatus(HttpServletResponse.SC_UNAUTHORIZED);
29+
response.setContentType(MediaType.APPLICATION_JSON_VALUE);
30+
response.setCharacterEncoding("UTF-8");
31+
32+
ErrorResponse errorResponse = ErrorResponse.of(ErrorCode.INVALID_TOKEN, request.getRequestURI());
33+
34+
response.getWriter().write(objectMapper.writeValueAsString(errorResponse));
35+
}
36+
}

src/main/java/com/climbup/climbup/common/dto/ApiResult.java

Lines changed: 18 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -9,36 +9,53 @@
99
@Schema(description = "Api 응답 정보")
1010
public class ApiResult<T> {
1111

12+
@Schema(description = "성공 여부", example = "true")
13+
private Boolean success;
14+
1215
@Schema(description = "응답 메시지", example = "요청이 성공적으로 처리되었습니다.")
1316
private String message;
1417

1518
@Schema(description = "응답 데이터")
1619
private T data;
1720

21+
@Schema(description = "에러 코드", example = "AUTH_001")
22+
private String errorCode;
23+
1824
public static <T> ApiResult<T> success(T data) {
1925
return ApiResult.<T>builder()
26+
.success(true)
2027
.message("요청이 성공적으로 처리되었습니다.")
2128
.data(data)
2229
.build();
2330
}
2431

2532
public static <T> ApiResult<T> success(String message, T data) {
2633
return ApiResult.<T>builder()
34+
.success(true)
2735
.message(message)
2836
.data(data)
2937
.build();
3038
}
3139

3240
public static ApiResult<Void> success() {
3341
return ApiResult.<Void>builder()
42+
.success(true)
3443
.message("요청이 성공적으로 처리되었습니다.")
3544
.build();
3645
}
3746

3847
public static ApiResult<Void> success(String message) {
3948
return ApiResult.<Void>builder()
49+
.success(true)
4050
.message(message)
4151
.build();
4252
}
4353

44-
}
54+
public static <T> ApiResult<T> error(String errorCode, String message) {
55+
return ApiResult.<T>builder()
56+
.success(false)
57+
.errorCode(errorCode)
58+
.message(message)
59+
.build();
60+
}
61+
}

src/main/java/com/climbup/climbup/global/config/SecurityConfig.java

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,7 @@
11
package com.climbup.climbup.global.config;
22

33
import com.climbup.climbup.auth.filter.JwtAuthenticationFilter;
4+
import com.climbup.climbup.auth.handler.CustomAuthenticationEntryPoint;
45
import com.climbup.climbup.auth.handler.OAuth2SuccessHandler;
56
import com.climbup.climbup.auth.service.CustomOAuth2UserService;
67
import io.swagger.v3.oas.models.Components;
@@ -26,6 +27,7 @@ public class SecurityConfig {
2627
private final CustomOAuth2UserService customOAuth2UserService;
2728
private final OAuth2SuccessHandler oAuth2SuccessHandler;
2829
private final JwtAuthenticationFilter jwtAuthenticationFilter;
30+
private final CustomAuthenticationEntryPoint customAuthenticationEntryPoint;
2931

3032
@Bean
3133
public SecurityFilterChain filterChain(HttpSecurity http) throws Exception {
@@ -56,6 +58,9 @@ public SecurityFilterChain filterChain(HttpSecurity http) throws Exception {
5658
.successHandler(oAuth2SuccessHandler)
5759
.failureUrl("/login?error")
5860
)
61+
.exceptionHandling(exceptions -> exceptions
62+
.authenticationEntryPoint(customAuthenticationEntryPoint)
63+
)
5964
.addFilterBefore(jwtAuthenticationFilter, UsernamePasswordAuthenticationFilter.class);
6065

6166
return http.build();

0 commit comments

Comments
 (0)