From 820d31065a8f516cfcc19eb80504d7254e4dffc7 Mon Sep 17 00:00:00 2001 From: Eunhee Baek <78892355+ehBeak@users.noreply.github.com> Date: Fri, 23 Aug 2024 09:40:46 +0900 Subject: [PATCH] =?UTF-8?q?[BE]=20=EC=9A=94=EC=B2=AD=20=EB=A1=9C=EA=B7=B8?= =?UTF-8?q?=EC=97=90=20=EC=82=AC=EC=9A=A9=EC=9E=90=20=EC=A0=95=EB=B3=B4?= =?UTF-8?q?=EB=A5=BC=20=EC=B6=94=EA=B0=80=20(#298)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit * refactor: IP 주소 정보 삭제 * feat: 요청에 사용자 정보 추가 * fix: 예외 발생시 500응답 수정 * refactor: 패키지 이름 수정 * refactor: 역할에 따라 인터셉터 분 * refactor: userInfo 상수로 추출 * refactor: 인터셉터 등록 순서 명시적으로 지정 * refactor: 인터셉터 이름 수정 * refactor: 응답 로그에도 사용자 정보 추가 * refactor: MDC를 통해서 유저 정보를 가져오도록 수정 --- .../main/java/kr/momo/config/WebConfig.java | 13 +++++ .../kr/momo/config/filter/FilterConfig.java | 29 ----------- .../java/kr/momo/config/filter/LogFilter.java | 42 --------------- .../config/interceptor/JwtInterceptor.java | 51 +++++++++++++++++++ .../{filter => interceptor}/LogGenerator.java | 20 ++++++-- .../interceptor/LoggingInterceptor.java | 41 +++++++++++++++ .../TraceIdGenerator.java | 2 +- .../exception/GlobalExceptionHandler.java | 8 +-- 8 files changed, 126 insertions(+), 80 deletions(-) delete mode 100644 backend/src/main/java/kr/momo/config/filter/FilterConfig.java delete mode 100644 backend/src/main/java/kr/momo/config/filter/LogFilter.java create mode 100644 backend/src/main/java/kr/momo/config/interceptor/JwtInterceptor.java rename backend/src/main/java/kr/momo/config/{filter => interceptor}/LogGenerator.java (53%) create mode 100644 backend/src/main/java/kr/momo/config/interceptor/LoggingInterceptor.java rename backend/src/main/java/kr/momo/config/{filter => interceptor}/TraceIdGenerator.java (86%) diff --git a/backend/src/main/java/kr/momo/config/WebConfig.java b/backend/src/main/java/kr/momo/config/WebConfig.java index 35d0d078c..df00fa4b1 100644 --- a/backend/src/main/java/kr/momo/config/WebConfig.java +++ b/backend/src/main/java/kr/momo/config/WebConfig.java @@ -1,20 +1,33 @@ package kr.momo.config; import java.util.List; +import kr.momo.config.interceptor.JwtInterceptor; +import kr.momo.config.interceptor.LoggingInterceptor; import kr.momo.controller.auth.AuthArgumentResolver; import lombok.RequiredArgsConstructor; import org.springframework.context.annotation.Configuration; import org.springframework.web.method.support.HandlerMethodArgumentResolver; +import org.springframework.web.servlet.config.annotation.InterceptorRegistry; import org.springframework.web.servlet.config.annotation.WebMvcConfigurer; @Configuration @RequiredArgsConstructor public class WebConfig implements WebMvcConfigurer { + private static final String BASE_URL = "/api/v1/**"; + private final AuthArgumentResolver authArgumentResolver; + private final JwtInterceptor jwtInterceptor; + private final LoggingInterceptor loggingInterceptor; @Override public void addArgumentResolvers(List resolvers) { resolvers.add(authArgumentResolver); } + + @Override + public void addInterceptors(InterceptorRegistry registry) { + registry.addInterceptor(jwtInterceptor).addPathPatterns(BASE_URL).order(1); + registry.addInterceptor(loggingInterceptor).addPathPatterns(BASE_URL).order(2); + } } diff --git a/backend/src/main/java/kr/momo/config/filter/FilterConfig.java b/backend/src/main/java/kr/momo/config/filter/FilterConfig.java deleted file mode 100644 index fbdec8729..000000000 --- a/backend/src/main/java/kr/momo/config/filter/FilterConfig.java +++ /dev/null @@ -1,29 +0,0 @@ -package kr.momo.config.filter; - -import jakarta.servlet.Filter; -import lombok.RequiredArgsConstructor; -import org.springframework.boot.web.servlet.FilterRegistrationBean; -import org.springframework.context.annotation.Bean; -import org.springframework.context.annotation.Configuration; - -@Configuration -@RequiredArgsConstructor -public class FilterConfig { - - private static final String BASE_URL = "/api/v1/*"; - private static final int FIRST_ORDER = 0; - - private final TraceIdGenerator traceIdGenerator; - private final LogGenerator logGenerator; - - @Bean - public FilterRegistrationBean logFilter() { - FilterRegistrationBean filterRegistrationBean = new FilterRegistrationBean<>(); - - filterRegistrationBean.setFilter(new LogFilter(traceIdGenerator, logGenerator)); - filterRegistrationBean.addUrlPatterns(BASE_URL); - filterRegistrationBean.setOrder(FIRST_ORDER); - - return filterRegistrationBean; - } -} diff --git a/backend/src/main/java/kr/momo/config/filter/LogFilter.java b/backend/src/main/java/kr/momo/config/filter/LogFilter.java deleted file mode 100644 index e66464b48..000000000 --- a/backend/src/main/java/kr/momo/config/filter/LogFilter.java +++ /dev/null @@ -1,42 +0,0 @@ -package kr.momo.config.filter; - -import jakarta.servlet.Filter; -import jakarta.servlet.FilterChain; -import jakarta.servlet.ServletException; -import jakarta.servlet.ServletRequest; -import jakarta.servlet.ServletResponse; -import jakarta.servlet.http.HttpServletRequest; -import jakarta.servlet.http.HttpServletResponse; -import java.io.IOException; -import lombok.RequiredArgsConstructor; -import lombok.extern.slf4j.Slf4j; -import org.slf4j.MDC; -import org.slf4j.MDC.MDCCloseable; - -@Slf4j -@RequiredArgsConstructor -public class LogFilter implements Filter { - - public static final String TRACE_ID = "traceId"; - - private final TraceIdGenerator traceIdGenerator; - private final LogGenerator logGenerator; - - @Override - public void doFilter(ServletRequest servletRequest, ServletResponse servletResponse, FilterChain filterChain) - throws IOException, ServletException { - - HttpServletRequest httpRequest = (HttpServletRequest) servletRequest; - HttpServletResponse httpResponse = (HttpServletResponse) servletResponse; - - String traceId = traceIdGenerator.generateShortUuid(); - - try (MDCCloseable ignored = MDC.putCloseable(TRACE_ID, traceId)) { - logGenerator.logRequest(traceId, httpRequest); - long startTime = System.currentTimeMillis(); - filterChain.doFilter(servletRequest, servletResponse); - long duration = System.currentTimeMillis() - startTime; - logGenerator.logResponse(traceId, duration, httpRequest, httpResponse); - } - } -} diff --git a/backend/src/main/java/kr/momo/config/interceptor/JwtInterceptor.java b/backend/src/main/java/kr/momo/config/interceptor/JwtInterceptor.java new file mode 100644 index 000000000..034a3e040 --- /dev/null +++ b/backend/src/main/java/kr/momo/config/interceptor/JwtInterceptor.java @@ -0,0 +1,51 @@ +package kr.momo.config.interceptor; + +import jakarta.servlet.http.Cookie; +import jakarta.servlet.http.HttpServletRequest; +import jakarta.servlet.http.HttpServletResponse; +import java.util.Arrays; +import java.util.Optional; +import kr.momo.service.auth.JwtManager; +import lombok.RequiredArgsConstructor; +import org.slf4j.MDC; +import org.springframework.stereotype.Component; +import org.springframework.web.servlet.HandlerInterceptor; + +@Component +@RequiredArgsConstructor +public class JwtInterceptor implements HandlerInterceptor { + + public static final String USER_INFO = "userInfo"; + + private static final String ANONYMOUS = "ANONYMOUS"; + private static final String ACCESS_TOKEN = "ACCESS_TOKEN"; + + private final JwtManager jwtManager; + + @Override + public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) { + Cookie[] cookies = request.getCookies(); + String userInfo = getCookieValue(cookies).orElse(ANONYMOUS); + if (isLoginUser(userInfo)) { + userInfo = String.valueOf(jwtManager.extract(userInfo)); + } + MDC.put(USER_INFO, userInfo); + + return true; + } + + private Optional getCookieValue(Cookie[] cookies) { + if (cookies == null) { + return Optional.empty(); + } + + return Arrays.stream(cookies) + .filter(cookie -> ACCESS_TOKEN.equals(cookie.getName())) + .map(Cookie::getValue) + .findFirst(); + } + + private boolean isLoginUser(String token) { + return !ANONYMOUS.equals(token); + } +} diff --git a/backend/src/main/java/kr/momo/config/filter/LogGenerator.java b/backend/src/main/java/kr/momo/config/interceptor/LogGenerator.java similarity index 53% rename from backend/src/main/java/kr/momo/config/filter/LogGenerator.java rename to backend/src/main/java/kr/momo/config/interceptor/LogGenerator.java index fca91f4fe..e3bfbad6f 100644 --- a/backend/src/main/java/kr/momo/config/filter/LogGenerator.java +++ b/backend/src/main/java/kr/momo/config/interceptor/LogGenerator.java @@ -1,27 +1,39 @@ -package kr.momo.config.filter; +package kr.momo.config.interceptor; import jakarta.servlet.http.HttpServletRequest; import jakarta.servlet.http.HttpServletResponse; +import lombok.RequiredArgsConstructor; import lombok.extern.slf4j.Slf4j; +import org.slf4j.MDC; import org.springframework.stereotype.Component; @Slf4j @Component +@RequiredArgsConstructor public class LogGenerator { public void logRequest(String traceId, HttpServletRequest request) { String httpMethod = request.getMethod(); String requestURI = request.getRequestURI(); - String remoteAddr = request.getRemoteAddr(); + String userInfo = MDC.get(JwtInterceptor.USER_INFO); - log.info("REQUEST [{}][{} {}][{}]", traceId, httpMethod, requestURI, remoteAddr); + log.info("REQUEST [{}][USERID:{}][{} {}]", traceId, userInfo, httpMethod, requestURI); } public void logResponse(String traceId, long duration, HttpServletRequest request, HttpServletResponse response) { String httpMethod = request.getMethod(); String requestURI = request.getRequestURI(); + String userInfo = MDC.get(JwtInterceptor.USER_INFO); int status = response.getStatus(); - log.info("RESPONSE [{}][{} {}][{} ms][Status: {}]", traceId, httpMethod, requestURI, duration, status); + log.info( + "RESPONSE [{}][USERID:{}][{} {}][{} ms][Status: {}]", + traceId, + userInfo, + httpMethod, + requestURI, + duration, + status + ); } } diff --git a/backend/src/main/java/kr/momo/config/interceptor/LoggingInterceptor.java b/backend/src/main/java/kr/momo/config/interceptor/LoggingInterceptor.java new file mode 100644 index 000000000..63283c378 --- /dev/null +++ b/backend/src/main/java/kr/momo/config/interceptor/LoggingInterceptor.java @@ -0,0 +1,41 @@ +package kr.momo.config.interceptor; + +import jakarta.servlet.http.HttpServletRequest; +import jakarta.servlet.http.HttpServletResponse; +import lombok.RequiredArgsConstructor; +import lombok.extern.slf4j.Slf4j; +import org.slf4j.MDC; +import org.springframework.stereotype.Component; +import org.springframework.web.servlet.HandlerInterceptor; + +@Slf4j +@RequiredArgsConstructor +@Component +public class LoggingInterceptor implements HandlerInterceptor { + + public static final String TRACE_ID = "traceId"; + private static final String START_TIME = "startTime"; + + private final TraceIdGenerator traceIdGenerator; + private final LogGenerator logGenerator; + + @Override + public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) { + String traceId = traceIdGenerator.generateShortUuid(); + MDC.put(TRACE_ID, traceId); + logGenerator.logRequest(traceId, request); + request.setAttribute(START_TIME, System.currentTimeMillis()); + return true; + } + + @Override + public void afterCompletion( + HttpServletRequest request, HttpServletResponse response, Object handler, Exception ex + ) { + long startTime = (Long) request.getAttribute(START_TIME); + long duration = System.currentTimeMillis() - startTime; + String traceId = MDC.get(TRACE_ID); + logGenerator.logResponse(traceId, duration, request, response); + MDC.clear(); + } +} diff --git a/backend/src/main/java/kr/momo/config/filter/TraceIdGenerator.java b/backend/src/main/java/kr/momo/config/interceptor/TraceIdGenerator.java similarity index 86% rename from backend/src/main/java/kr/momo/config/filter/TraceIdGenerator.java rename to backend/src/main/java/kr/momo/config/interceptor/TraceIdGenerator.java index 48cf5494d..9426b67a3 100644 --- a/backend/src/main/java/kr/momo/config/filter/TraceIdGenerator.java +++ b/backend/src/main/java/kr/momo/config/interceptor/TraceIdGenerator.java @@ -1,4 +1,4 @@ -package kr.momo.config.filter; +package kr.momo.config.interceptor; import java.util.UUID; import org.springframework.stereotype.Component; diff --git a/backend/src/main/java/kr/momo/exception/GlobalExceptionHandler.java b/backend/src/main/java/kr/momo/exception/GlobalExceptionHandler.java index 88a7d5780..2ee59d6d5 100644 --- a/backend/src/main/java/kr/momo/exception/GlobalExceptionHandler.java +++ b/backend/src/main/java/kr/momo/exception/GlobalExceptionHandler.java @@ -1,6 +1,6 @@ package kr.momo.exception; -import kr.momo.config.filter.LogFilter; +import kr.momo.config.interceptor.LoggingInterceptor; import lombok.extern.slf4j.Slf4j; import org.slf4j.MDC; import org.springframework.http.HttpStatus; @@ -20,7 +20,7 @@ public class GlobalExceptionHandler { @ExceptionHandler public ProblemDetail handleMomoException(MomoException ex) { - String traceId = MDC.get(LogFilter.TRACE_ID); + String traceId = MDC.get(LoggingInterceptor.TRACE_ID); log.warn(EXCEPTION_LOG_FORMAT, traceId, ex); ProblemDetail problemDetail = ProblemDetail.forStatusAndDetail(ex.httpStatus(), ex.message()); @@ -29,7 +29,7 @@ public ProblemDetail handleMomoException(MomoException ex) { @ExceptionHandler public ProblemDetail handleMethodArgumentNotValidException(MethodArgumentNotValidException ex) { - String traceId = MDC.get(LogFilter.TRACE_ID); + String traceId = MDC.get(LoggingInterceptor.TRACE_ID); log.warn(EXCEPTION_LOG_FORMAT, traceId, ex); ProblemDetail problemDetail = ProblemDetail.forStatusAndDetail( @@ -40,7 +40,7 @@ public ProblemDetail handleMethodArgumentNotValidException(MethodArgumentNotVali @ExceptionHandler public ProblemDetail handleInternalException(Exception ex) { - String traceId = MDC.get(LogFilter.TRACE_ID); + String traceId = MDC.get(LoggingInterceptor.TRACE_ID); log.error(EXCEPTION_LOG_FORMAT, traceId, ex); return ProblemDetail.forStatusAndDetail(HttpStatus.INTERNAL_SERVER_ERROR, INTERNAL_SERVER_ERROR_MESSAGE);