Skip to content

Commit 2914ae5

Browse files
committed
fix: 필터 레벨에서도 userId MDC 최선 노력 채우기
@userid 파라미터가 없는 요청(토큰 재발급, 배너 등)이나 인자 리졸브 이전 단계에서 예외가 나는 경우 userId가 로그에 안 남는 문제를 MdcLoggingFilter에서 accessToken을 미리 파싱해두는 방식으로 보완. 실제 인증 검증/방문자 모드 처리는 UserIdResolver가 그대로 담당하고, 그 결과가 이 값을 덮어쓴다. 로컬 DB/Redis 띄우고 실제 JWT로 검증: - @userid 있는 요청: 요청 진입 로그부터 userId 표시 - @userid 없는 공개 엔드포인트: 토큰만 있으면 userId 표시
1 parent f1a7044 commit 2914ae5

1 file changed

Lines changed: 27 additions & 1 deletion

File tree

‎src/main/java/org/runnect/server/config/logging/MdcLoggingFilter.java‎

Lines changed: 27 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,9 @@
11
package org.runnect.server.config.logging;
22

3+
import lombok.RequiredArgsConstructor;
34
import lombok.extern.slf4j.Slf4j;
5+
import org.runnect.server.common.constant.TokenStatus;
6+
import org.runnect.server.config.jwt.JwtService;
47
import org.slf4j.MDC;
58
import org.springframework.stereotype.Component;
69

@@ -17,13 +20,21 @@
1720
* 요청마다 traceId를 발급해 MDC에 담아둔다.
1821
* 로그 패턴에 %X{traceId}를 포함시키면(logback-spring.xml), 여러 요청이 뒤섞인 로그에서도
1922
* 같은 traceId로 특정 요청의 흐름만 추적할 수 있다.
23+
*
24+
* userId는 @UserId 파라미터가 없는 요청(토큰 재발급, 배너 등)에서도 로그에 남도록
25+
* 여기서 best-effort로 한 번 더 채운다. 실제 인증 검증/방문자 모드 처리는 UserIdResolver가
26+
* 맡고, 그 결과가 이후 이 값을 덮어쓴다.
2027
*/
2128
@Slf4j
2229
@Component
30+
@RequiredArgsConstructor
2331
public class MdcLoggingFilter implements Filter {
2432

2533
private static final String TRACE_ID_KEY = "traceId";
2634
private static final int TRACE_ID_LENGTH = 8;
35+
private static final String USER_ID_KEY = "userId";
36+
37+
private final JwtService jwtService;
2738

2839
@Override
2940
public void doFilter(ServletRequest request, ServletResponse response, FilterChain chain)
@@ -32,11 +43,26 @@ public void doFilter(ServletRequest request, ServletResponse response, FilterCha
3243
try {
3344
MDC.put(TRACE_ID_KEY, traceId);
3445
HttpServletRequest httpRequest = (HttpServletRequest) request;
46+
populateUserIdBestEffort(httpRequest);
3547
log.info("{} {}", httpRequest.getMethod(), httpRequest.getRequestURI());
3648
chain.doFilter(request, response);
3749
} finally {
3850
MDC.remove(TRACE_ID_KEY);
39-
MDC.remove("userId");
51+
MDC.remove(USER_ID_KEY);
52+
}
53+
}
54+
55+
private void populateUserIdBestEffort(HttpServletRequest request) {
56+
String accessToken = request.getHeader("accessToken");
57+
if (accessToken == null) {
58+
return;
59+
}
60+
try {
61+
if (jwtService.verifyToken(accessToken) == TokenStatus.TOKEN_VALID) {
62+
MDC.put(USER_ID_KEY, jwtService.getJwtContents(accessToken));
63+
}
64+
} catch (RuntimeException e) {
65+
// 로깅 목적의 best-effort 파싱이므로 실패해도 요청 처리는 계속 진행한다.
4066
}
4167
}
4268
}

0 commit comments

Comments
 (0)