From 9662eda4bf9e66027a5cbe31f55ab3721aa676ca Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?=EC=B2=9C=20=EC=A7=84=EA=B0=95?= <jjjjjk12@ajou.ac.kr>
Date: Sat, 29 Mar 2025 13:54:43 +0900
Subject: [PATCH] =?UTF-8?q?feat:=20=EC=9D=B8=EC=A6=9D=20=EC=9D=B8=ED=84=B0?=
 =?UTF-8?q?=EC=85=89=ED=84=B0=EC=97=90=EC=84=9C=20=ED=95=84=ED=84=B0?=
 =?UTF-8?q?=EB=A1=9C=20=EB=B3=80=EA=B2=BD=20=EB=B0=8F=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=20?=
 =?UTF-8?q?=EC=B6=94=EA=B0=80?=
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit

---
 .../{AuthInterceptor.java => AuthFilter.java} | 153 +++++++++---------
 .../com/aolda/itda/config/LoggingFilter.java  |  15 +-
 .../java/com/aolda/itda/config/WebConfig.java |  27 +++-
 3 files changed, 107 insertions(+), 88 deletions(-)
 rename src/main/java/com/aolda/itda/config/{AuthInterceptor.java => AuthFilter.java} (71%)

diff --git a/src/main/java/com/aolda/itda/config/AuthInterceptor.java b/src/main/java/com/aolda/itda/config/AuthFilter.java
similarity index 71%
rename from src/main/java/com/aolda/itda/config/AuthInterceptor.java
rename to src/main/java/com/aolda/itda/config/AuthFilter.java
index fd78fb6..f810c2c 100644
--- a/src/main/java/com/aolda/itda/config/AuthInterceptor.java
+++ b/src/main/java/com/aolda/itda/config/AuthFilter.java
@@ -1,77 +1,76 @@
-package com.aolda.itda.config;
-
-import com.aolda.itda.dto.auth.IdAndNameDTO;
-import com.aolda.itda.exception.CustomException;
-import com.aolda.itda.exception.ErrorCode;
-import com.aolda.itda.service.AuthService;
-import jakarta.servlet.http.HttpServletRequest;
-import jakarta.servlet.http.HttpServletResponse;
-import lombok.RequiredArgsConstructor;
-import lombok.extern.slf4j.Slf4j;
-import org.springframework.stereotype.Component;
-import org.springframework.web.servlet.HandlerInterceptor;
-
-import java.util.ArrayList;
-import java.util.List;
-import java.util.Map;
-
-@RequiredArgsConstructor
-@Component
-@Slf4j
-public class AuthInterceptor implements HandlerInterceptor {
-
-    private final AuthService authService;
-
-    @Override
-    public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception {
-        String token = request.getHeader("X-Subject-Token");
-
-        /* 토큰 헤더 검증 */
-        if (token == null || token.isEmpty()) {
-            throw new CustomException(ErrorCode.INVALID_TOKEN, request.getRequestURI());
-        }
-
-        /* 유효 토큰 검증 */
-        String userId = authService.validateTokenAndGetUserId(token);
-        if (userId == null) {
-            log.error("Token validation failed for URI {}: {}", request.getRequestURI(), request.getRemoteAddr());
-            throw new CustomException(ErrorCode.INVALID_TOKEN, request.getRequestURI());
-        }
-
-        /* 프로젝트 권한 검증 */
-        String projectId = request.getParameter("projectId");
-        if (projectId != null) {
-
-            try {
-                authService.getBestRoleWithinProject(token, projectId).get("role");
-                if (!request.getMethod().equals("GET") && !authService.getBestRoleWithinProject(token, projectId).get("role").equals("admin")) {
-                    throw new CustomException(ErrorCode.UNAUTHORIZED_USER, request.getRequestURI());
-
-                }
-            } catch (Exception e) {
-                throw new CustomException(ErrorCode.UNAUTHORIZED_USER, request.getRequestURI());
-            }
-
-
-
-        }
-
-        /* 프로젝트 리스트 조회 */
-        List<String> projects;
-        if (authService.isAdmin(Map.of("id", userId, "token", token))) {
-            projects = authService.getAllProjects(token).stream().map(IdAndNameDTO::getId)
-                    .toList();
-        }
-
-        else {
-            projects = authService.getProjectsWithUser(Map.of("id", userId, "token", token))
-                    .stream().map(IdAndNameDTO::getId)
-                    .toList();
-        }
-
-        request.setAttribute("projects", projects);
-        request.setAttribute("user", Map.of("id", userId, "token", token));
-        return true;
-
-    }
-}
+package com.aolda.itda.config;
+
+import com.aolda.itda.dto.auth.IdAndNameDTO;
+import com.aolda.itda.exception.CustomException;
+import com.aolda.itda.exception.ErrorCode;
+import com.aolda.itda.service.AuthService;
+import jakarta.servlet.FilterChain;
+import jakarta.servlet.ServletException;
+import jakarta.servlet.http.HttpServletRequest;
+import jakarta.servlet.http.HttpServletResponse;
+import lombok.RequiredArgsConstructor;
+import lombok.extern.slf4j.Slf4j;
+import org.springframework.stereotype.Component;
+import org.springframework.web.filter.OncePerRequestFilter;
+
+import java.io.IOException;
+import java.util.List;
+import java.util.Map;
+
+@RequiredArgsConstructor
+@Component
+@Slf4j
+public class AuthFilter extends OncePerRequestFilter {
+
+    private final AuthService authService;
+
+    @Override
+    protected void doFilterInternal(HttpServletRequest request, HttpServletResponse response, FilterChain filterChain)
+            throws ServletException, IOException {
+
+        if (request.getRequestURI().contains("/api/auth")) {
+            filterChain.doFilter(request, response);
+            return;
+        }
+
+        String token = request.getHeader("X-Subject-Token");
+
+        // 토큰 헤더 검증
+        if (token == null || token.isEmpty()) {
+            throw new CustomException(ErrorCode.INVALID_TOKEN, request.getRequestURI());
+        }
+
+        // 유효 토큰 검증
+        String userId = authService.validateTokenAndGetUserId(token);
+        if (userId == null) {
+            log.error("Token validation failed for URI {}: {}", request.getRequestURI(), request.getRemoteAddr());
+            throw new CustomException(ErrorCode.INVALID_TOKEN, request.getRequestURI());
+        }
+
+        // 프로젝트 권한 검증
+        String projectId = request.getParameter("projectId");
+        if (projectId != null) {
+            try {
+                authService.getBestRoleWithinProject(token, projectId).get("role");
+                if (!request.getMethod().equals("GET") && !authService.getBestRoleWithinProject(token, projectId).get("role").equals("admin")) {
+                    throw new CustomException(ErrorCode.UNAUTHORIZED_USER, request.getRequestURI());
+                }
+            } catch (Exception e) {
+                throw new CustomException(ErrorCode.UNAUTHORIZED_USER, request.getRequestURI());
+            }
+        }
+
+        // 프로젝트 리스트 조회
+        List<String> projects;
+        if (authService.isAdmin(Map.of("id", userId, "token", token))) {
+            projects = authService.getAllProjects(token).stream().map(IdAndNameDTO::getId).toList();
+        } else {
+            projects = authService.getProjectsWithUser(Map.of("id", userId, "token", token)).stream().map(IdAndNameDTO::getId).toList();
+        }
+
+        request.setAttribute("projects", projects);
+        request.setAttribute("user", Map.of("id", userId, "token", token));
+
+        filterChain.doFilter(request, response);
+    }
+}
\ No newline at end of file
diff --git a/src/main/java/com/aolda/itda/config/LoggingFilter.java b/src/main/java/com/aolda/itda/config/LoggingFilter.java
index f2330bf..8c5c2f0 100644
--- a/src/main/java/com/aolda/itda/config/LoggingFilter.java
+++ b/src/main/java/com/aolda/itda/config/LoggingFilter.java
@@ -1,9 +1,14 @@
 package com.aolda.itda.config;
 
+import com.aolda.itda.exception.CustomException;
+import com.aolda.itda.exception.ErrorCode;
+import com.aolda.itda.service.AuthService;
+import com.fasterxml.jackson.core.JsonProcessingException;
 import jakarta.servlet.FilterChain;
 import jakarta.servlet.ServletException;
 import jakarta.servlet.http.HttpServletRequest;
 import jakarta.servlet.http.HttpServletResponse;
+import lombok.RequiredArgsConstructor;
 import org.slf4j.Logger;
 import org.slf4j.LoggerFactory;
 import org.springframework.stereotype.Component;
@@ -11,11 +16,14 @@ import org.springframework.web.filter.OncePerRequestFilter;
 import org.springframework.web.util.ContentCachingRequestWrapper;
 
 import java.io.IOException;
+import java.util.Map;
 
 @Component
+@RequiredArgsConstructor
 public class LoggingFilter extends OncePerRequestFilter {
 
     private static final Logger logger = LoggerFactory.getLogger(LoggingFilter.class);
+    private final AuthService authService;
 
     @Override
     protected void doFilterInternal(HttpServletRequest request, HttpServletResponse response, FilterChain filterChain)
@@ -29,15 +37,16 @@ public class LoggingFilter extends OncePerRequestFilter {
         logRequest(cachingRequest);
     }
 
-    private void logRequest(ContentCachingRequestWrapper request) {
+    private void logRequest(ContentCachingRequestWrapper request) throws JsonProcessingException {
         String ip = request.getRemoteAddr();
         String method = request.getMethod();
         String uri = request.getRequestURI();
         String queryString = request.getQueryString();
         String body = getRequestBody(request);
+        Map<String, String> user = (Map<String, String>) request.getAttribute("user");
 
-        logger.info("IP: {}, Method: {}, URI: {}, Query Params: {}, Request Body: {}",
-                ip, method, uri, (queryString != null ? queryString : "None"),
+        logger.info("IP: {}, Method: {}, URI: {}, Query Params: {}, User: {}, Request Body: {}",
+                ip, method, uri, (queryString != null ? queryString : "None"), (user != null ? user.get("id") : "None"),
                 (!body.isEmpty() ? body : "None"));
     }
 
diff --git a/src/main/java/com/aolda/itda/config/WebConfig.java b/src/main/java/com/aolda/itda/config/WebConfig.java
index e3893ae..a3559c4 100644
--- a/src/main/java/com/aolda/itda/config/WebConfig.java
+++ b/src/main/java/com/aolda/itda/config/WebConfig.java
@@ -3,17 +3,18 @@ package com.aolda.itda.config;
 import com.querydsl.jpa.impl.JPAQueryFactory;
 import jakarta.persistence.EntityManager;
 import lombok.RequiredArgsConstructor;
+import org.springframework.boot.web.servlet.FilterRegistrationBean;
 import org.springframework.context.annotation.Bean;
 import org.springframework.context.annotation.Configuration;
 import org.springframework.web.servlet.config.annotation.CorsRegistry;
-import org.springframework.web.servlet.config.annotation.InterceptorRegistry;
 import org.springframework.web.servlet.config.annotation.WebMvcConfigurer;
 
 @Configuration
 @RequiredArgsConstructor
 public class WebConfig implements WebMvcConfigurer {
 
-    private final AuthInterceptor authInterceptor;
+    private final AuthFilter authFilter;
+    private final LoggingFilter loggingFilter;
 
     @Override
     public void addCorsMappings(CorsRegistry registry) { // 스프링단에서 cors 설정
@@ -26,13 +27,23 @@ public class WebConfig implements WebMvcConfigurer {
         ;
     }
 
-    @Override
-    public void addInterceptors(InterceptorRegistry registry) {
-        String[] excludeAuth = {"/error", "/api/auth/*" };
 
-        registry.addInterceptor(authInterceptor)
-                .addPathPatterns("/**")
-                .excludePathPatterns(excludeAuth);
+    @Bean
+    public FilterRegistrationBean<AuthFilter> authFilterRegistration() {
+        FilterRegistrationBean<AuthFilter> registrationBean = new FilterRegistrationBean<>();
+        registrationBean.setFilter(authFilter);
+        registrationBean.setOrder(1); // AuthFilter의 순서를 1로 설정
+        registrationBean.addUrlPatterns("/*");
+        return registrationBean;
+    }
+
+    @Bean
+    public FilterRegistrationBean<LoggingFilter> loggingFilterRegistration() {
+        FilterRegistrationBean<LoggingFilter> registrationBean = new FilterRegistrationBean<>();
+        registrationBean.setFilter(loggingFilter);
+        registrationBean.setOrder(2); // LoggingFilter의 순서를 2로 설정
+        registrationBean.addUrlPatterns("/*");
+        return registrationBean;
     }
 
     @Bean
-- 
GitLab