From bd21e3ebc95a5c8c013e60ed7dc3eb64436344a4 Mon Sep 17 00:00:00 2001 From: seungwookc97 Date: Thu, 25 Sep 2025 12:28:42 +0900 Subject: [PATCH 1/3] =?UTF-8?q?chore:dev=20->=20main=20=EB=B3=91=ED=95=A9?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- Dockerfile | 1 + 1 file changed, 1 insertion(+) diff --git a/Dockerfile b/Dockerfile index 30d4b0ca..e9231c4c 100644 --- a/Dockerfile +++ b/Dockerfile @@ -18,6 +18,7 @@ COPY src src # 애플리케이션 빌드 #RUN gradle build --no-daemon +# 테스트 빌드 안하고 실행 RUN gradle build -x test --no-daemon # 두 번째 스테이지: 실행 스테이지 From 9272dbbe54ee1c01f71ac15942ff927e48dcc4ab Mon Sep 17 00:00:00 2001 From: seungwookc97 Date: Thu, 25 Sep 2025 14:00:07 +0900 Subject: [PATCH 2/3] =?UTF-8?q?refactor:=20=EC=A0=91=EB=91=90=EC=82=AC=20?= =?UTF-8?q?=EC=A0=9C=EA=B1=B0=20=EB=B0=8F=20security=20=ED=95=84=ED=84=B0?= =?UTF-8?q?=20=ED=86=B5=EA=B3=BC?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../chatbot/controller/ChatbotController.java | 2 +- .../controller/CocktailCommentController.java | 2 +- .../controller/CocktailController.java | 2 +- .../controller/CocktailShareController.java | 2 +- .../mybar/controller/MyBarController.java | 2 +- .../controller/MyHistoryController.java | 2 +- .../myhistory/service/MyHistoryService.java | 6 ++--- .../controller/NotificationController.java | 16 ++++--------- .../service/NotificationService.java | 13 +++++----- .../comment/controller/CommentController.java | 15 ++++-------- .../post/post/controller/PostController.java | 15 ++++-------- .../profile/controller/ProfileController.java | 2 +- .../security/CustomAuthenticationFilter.java | 24 +++++++------------ .../controller/CocktailControllerTest.java | 8 +++---- 14 files changed, 43 insertions(+), 68 deletions(-) diff --git a/src/main/java/com/back/domain/chatbot/controller/ChatbotController.java b/src/main/java/com/back/domain/chatbot/controller/ChatbotController.java index b9e12684..9247ffbc 100644 --- a/src/main/java/com/back/domain/chatbot/controller/ChatbotController.java +++ b/src/main/java/com/back/domain/chatbot/controller/ChatbotController.java @@ -14,7 +14,7 @@ import java.util.List; @RestController -@RequestMapping("/api/chatbot") +@RequestMapping("/chatbot") @RequiredArgsConstructor @Slf4j public class ChatbotController { diff --git a/src/main/java/com/back/domain/cocktail/comment/controller/CocktailCommentController.java b/src/main/java/com/back/domain/cocktail/comment/controller/CocktailCommentController.java index 0f29ac05..f1d40720 100644 --- a/src/main/java/com/back/domain/cocktail/comment/controller/CocktailCommentController.java +++ b/src/main/java/com/back/domain/cocktail/comment/controller/CocktailCommentController.java @@ -14,7 +14,7 @@ import java.util.List; @RestController -@RequestMapping("/api/cocktails/{cocktailId}/comments") +@RequestMapping("/cocktails/{cocktailId}/comments") @Tag(name = "ApiCocktailCommentController", description = "API 칵테일댓글 컨트롤러") @RequiredArgsConstructor public class CocktailCommentController { diff --git a/src/main/java/com/back/domain/cocktail/controller/CocktailController.java b/src/main/java/com/back/domain/cocktail/controller/CocktailController.java index 80296edc..de039b3f 100644 --- a/src/main/java/com/back/domain/cocktail/controller/CocktailController.java +++ b/src/main/java/com/back/domain/cocktail/controller/CocktailController.java @@ -15,7 +15,7 @@ import java.util.List; @RestController -@RequestMapping("api/cocktails") +@RequestMapping("cocktails") @Tag(name = "ApiCocktailController", description = "API 칵테일 컨트롤러") @RequiredArgsConstructor public class CocktailController { diff --git a/src/main/java/com/back/domain/cocktail/controller/CocktailShareController.java b/src/main/java/com/back/domain/cocktail/controller/CocktailShareController.java index c23afb1c..9b047b75 100644 --- a/src/main/java/com/back/domain/cocktail/controller/CocktailShareController.java +++ b/src/main/java/com/back/domain/cocktail/controller/CocktailShareController.java @@ -13,7 +13,7 @@ import java.util.Map; @RestController -@RequestMapping("/api/cocktails") +@RequestMapping("/cocktails") @RequiredArgsConstructor public class CocktailShareController { private final CocktailRepository cocktailRepository; diff --git a/src/main/java/com/back/domain/mybar/controller/MyBarController.java b/src/main/java/com/back/domain/mybar/controller/MyBarController.java index 45bb5190..845c7c06 100644 --- a/src/main/java/com/back/domain/mybar/controller/MyBarController.java +++ b/src/main/java/com/back/domain/mybar/controller/MyBarController.java @@ -14,7 +14,7 @@ import java.time.LocalDateTime; @RestController -@RequestMapping("/api/me/bar") +@RequestMapping("/me/bar") @RequiredArgsConstructor @Validated public class MyBarController { diff --git a/src/main/java/com/back/domain/myhistory/controller/MyHistoryController.java b/src/main/java/com/back/domain/myhistory/controller/MyHistoryController.java index 819b4a6a..383dbb00 100644 --- a/src/main/java/com/back/domain/myhistory/controller/MyHistoryController.java +++ b/src/main/java/com/back/domain/myhistory/controller/MyHistoryController.java @@ -18,7 +18,7 @@ import java.time.LocalDateTime; @RestController -@RequestMapping("/api/me") +@RequestMapping("/me") @RequiredArgsConstructor @Validated public class MyHistoryController { diff --git a/src/main/java/com/back/domain/myhistory/service/MyHistoryService.java b/src/main/java/com/back/domain/myhistory/service/MyHistoryService.java index 0758df28..c65dd67e 100644 --- a/src/main/java/com/back/domain/myhistory/service/MyHistoryService.java +++ b/src/main/java/com/back/domain/myhistory/service/MyHistoryService.java @@ -102,7 +102,7 @@ public MyHistoryCommentGoResponseDto getPostLinkFromMyComment(Long userId, Long throw new ServiceException(410, "삭제된 게시글입니다."); } Long postId = post.getId(); - String apiUrl = "/api/posts/" + postId; + String apiUrl = "/posts/" + postId; return new MyHistoryCommentGoResponseDto(postId, apiUrl); } @@ -116,7 +116,7 @@ public MyHistoryPostGoResponseDto getPostLinkFromMyPost(Long userId, Long postId if (p.getStatus() == PostStatus.DELETED) { throw new ServiceException(410, "삭제된 게시글입니다."); } - String apiUrl = "/api/posts/" + p.getId(); + String apiUrl = "/posts/" + p.getId(); return new MyHistoryPostGoResponseDto(p.getId(), apiUrl); } @@ -177,7 +177,7 @@ public MyHistoryPostGoResponseDto getPostLinkFromMyLikedPost(Long userId, Long p if (post.getStatus() == PostStatus.DELETED) { throw new ServiceException(410, "삭제된 게시글입니다."); } - String apiUrl = "/api/posts/" + post.getId(); + String apiUrl = "/posts/" + post.getId(); return new MyHistoryPostGoResponseDto(post.getId(), apiUrl); } } diff --git a/src/main/java/com/back/domain/notification/controller/NotificationController.java b/src/main/java/com/back/domain/notification/controller/NotificationController.java index 9b843278..00ee1dde 100644 --- a/src/main/java/com/back/domain/notification/controller/NotificationController.java +++ b/src/main/java/com/back/domain/notification/controller/NotificationController.java @@ -7,27 +7,21 @@ import com.back.domain.notification.service.NotificationService; import com.back.domain.notification.service.NotificationSettingService; import com.back.global.rsData.RsData; +import io.swagger.v3.oas.annotations.Operation; import jakarta.validation.Valid; import jakarta.validation.constraints.Max; import jakarta.validation.constraints.Min; -import io.swagger.v3.oas.annotations.Operation; -import java.time.LocalDateTime; import lombok.RequiredArgsConstructor; import org.springframework.format.annotation.DateTimeFormat; import org.springframework.security.core.annotation.AuthenticationPrincipal; import org.springframework.validation.annotation.Validated; -import org.springframework.web.bind.annotation.GetMapping; -import org.springframework.web.bind.annotation.PatchMapping; -import org.springframework.web.bind.annotation.PathVariable; -import org.springframework.web.bind.annotation.PostMapping; -import org.springframework.web.bind.annotation.RequestBody; -import org.springframework.web.bind.annotation.RequestMapping; -import org.springframework.web.bind.annotation.RequestParam; -import org.springframework.web.bind.annotation.RestController; +import org.springframework.web.bind.annotation.*; import org.springframework.web.servlet.mvc.method.annotation.SseEmitter; +import java.time.LocalDateTime; + @RestController -@RequestMapping("/api/me") +@RequestMapping("/me") @RequiredArgsConstructor @Validated public class NotificationController { diff --git a/src/main/java/com/back/domain/notification/service/NotificationService.java b/src/main/java/com/back/domain/notification/service/NotificationService.java index 674c9311..f4f572c9 100644 --- a/src/main/java/com/back/domain/notification/service/NotificationService.java +++ b/src/main/java/com/back/domain/notification/service/NotificationService.java @@ -10,17 +10,18 @@ import com.back.domain.user.entity.User; import com.back.global.exception.ServiceException; import com.back.global.rq.Rq; -import java.time.LocalDateTime; -import java.util.ArrayList; -import java.util.List; -import java.util.Map; -import java.util.concurrent.ConcurrentHashMap; import lombok.RequiredArgsConstructor; import org.springframework.data.domain.PageRequest; import org.springframework.stereotype.Service; import org.springframework.transaction.annotation.Transactional; import org.springframework.web.servlet.mvc.method.annotation.SseEmitter; +import java.time.LocalDateTime; +import java.util.ArrayList; +import java.util.List; +import java.util.Map; +import java.util.concurrent.ConcurrentHashMap; + @Service @RequiredArgsConstructor public class NotificationService { @@ -85,7 +86,7 @@ public NotificationGoResponseDto markAsReadAndGetPostLink(Long userId, Long noti notification.markRead(); } Long postId = notification.getPost().getId(); - String apiUrl = "/api/posts/" + postId; + String apiUrl = "/posts/" + postId; return new NotificationGoResponseDto(postId, apiUrl); } diff --git a/src/main/java/com/back/domain/post/comment/controller/CommentController.java b/src/main/java/com/back/domain/post/comment/controller/CommentController.java index d0a60b50..64716a7e 100644 --- a/src/main/java/com/back/domain/post/comment/controller/CommentController.java +++ b/src/main/java/com/back/domain/post/comment/controller/CommentController.java @@ -8,20 +8,13 @@ import io.swagger.v3.oas.annotations.Operation; import io.swagger.v3.oas.annotations.tags.Tag; import jakarta.validation.Valid; -import java.util.List; import lombok.RequiredArgsConstructor; -import org.springframework.web.bind.annotation.DeleteMapping; -import org.springframework.web.bind.annotation.GetMapping; -import org.springframework.web.bind.annotation.PatchMapping; -import org.springframework.web.bind.annotation.PathVariable; -import org.springframework.web.bind.annotation.PostMapping; -import org.springframework.web.bind.annotation.RequestBody; -import org.springframework.web.bind.annotation.RequestMapping; -import org.springframework.web.bind.annotation.RequestParam; -import org.springframework.web.bind.annotation.RestController; +import org.springframework.web.bind.annotation.*; + +import java.util.List; @RestController -@RequestMapping("/api/posts/{postId}/comments") +@RequestMapping("/posts/{postId}/comments") @Tag(name = "ApiCommentController", description = "API 댓글 컨트롤러") @RequiredArgsConstructor public class CommentController { diff --git a/src/main/java/com/back/domain/post/post/controller/PostController.java b/src/main/java/com/back/domain/post/post/controller/PostController.java index 3e23c8f0..1e2230fe 100644 --- a/src/main/java/com/back/domain/post/post/controller/PostController.java +++ b/src/main/java/com/back/domain/post/post/controller/PostController.java @@ -8,20 +8,13 @@ import io.swagger.v3.oas.annotations.Operation; import io.swagger.v3.oas.annotations.tags.Tag; import jakarta.validation.Valid; -import java.util.List; import lombok.RequiredArgsConstructor; -import org.springframework.web.bind.annotation.DeleteMapping; -import org.springframework.web.bind.annotation.GetMapping; -import org.springframework.web.bind.annotation.PatchMapping; -import org.springframework.web.bind.annotation.PathVariable; -import org.springframework.web.bind.annotation.PostMapping; -import org.springframework.web.bind.annotation.RequestBody; -import org.springframework.web.bind.annotation.RequestMapping; -import org.springframework.web.bind.annotation.RequestParam; -import org.springframework.web.bind.annotation.RestController; +import org.springframework.web.bind.annotation.*; + +import java.util.List; @RestController -@RequestMapping("/api/posts") +@RequestMapping("/posts") @Tag(name = "ApiPostController", description = "API 게시글 컨트롤러") @RequiredArgsConstructor public class PostController { diff --git a/src/main/java/com/back/domain/profile/controller/ProfileController.java b/src/main/java/com/back/domain/profile/controller/ProfileController.java index 7e23676e..f7d9eca3 100644 --- a/src/main/java/com/back/domain/profile/controller/ProfileController.java +++ b/src/main/java/com/back/domain/profile/controller/ProfileController.java @@ -12,7 +12,7 @@ import org.springframework.web.bind.annotation.*; @RestController -@RequestMapping("/api/me/profile") +@RequestMapping("/me/profile") @RequiredArgsConstructor public class ProfileController { diff --git a/src/main/java/com/back/global/security/CustomAuthenticationFilter.java b/src/main/java/com/back/global/security/CustomAuthenticationFilter.java index b01951b5..ccaff855 100644 --- a/src/main/java/com/back/global/security/CustomAuthenticationFilter.java +++ b/src/main/java/com/back/global/security/CustomAuthenticationFilter.java @@ -53,30 +53,24 @@ protected void doFilterInternal(HttpServletRequest request, HttpServletResponse private void work(HttpServletRequest request, HttpServletResponse response, FilterChain filterChain) throws ServletException, IOException { String uri = request.getRequestURI(); - String method = request.getMethod(); // SecurityConfig에서 permitAll()로 설정된 경로들은 필터를 통과시키기 if ( - //추후 로그인 필요한 api 추가 설정 uri.startsWith("/h2-console") || - uri.startsWith("/login/oauth2/") || - (method.equals("GET") && uri.equals("/api/~~")) || - (method.equals("POST") && uri.equals("/api/~")) - + uri.startsWith("/login/oauth2/") || + uri.startsWith("/oauth2/") || + uri.startsWith("/actuator/") || + uri.startsWith("/swagger-ui/") || + uri.startsWith("/api-docs/") || + uri.startsWith("/user/") || + uri.startsWith("/cocktails/") || + uri.startsWith("/chatbot/") || + uri.equals("/") ) { filterChain.doFilter(request, response); return; } - // 인증 필수 URL 확인 - boolean requiresAuth = uri.startsWith("/api/"); - - // 인증이 필요하지 않은 URL이면 그냥 통과 - if (!requiresAuth) { - filterChain.doFilter(request, response); - return; - } - // 쿠키에서 accessToken 가져오기 String accessToken = rq.getCookieValue("accessToken", ""); diff --git a/src/test/java/com/back/domain/cocktail/controller/CocktailControllerTest.java b/src/test/java/com/back/domain/cocktail/controller/CocktailControllerTest.java index dcf0a63b..438dae72 100644 --- a/src/test/java/com/back/domain/cocktail/controller/CocktailControllerTest.java +++ b/src/test/java/com/back/domain/cocktail/controller/CocktailControllerTest.java @@ -59,7 +59,7 @@ void t1() throws Exception { // when: GET 요청 ResultActions resultActions = mvc.perform( - get("/api/cocktails/{id}", savedCocktail.getId()) + get("/cocktails/{id}", savedCocktail.getId()) .contentType(MediaType.APPLICATION_JSON) ).andDo(print()); @@ -80,7 +80,7 @@ void t2() throws Exception { long nonExistentId = 9999L; ResultActions resultActions = mvc.perform( - get("/api/cocktails/{id}", nonExistentId) + get("/cocktails/{id}", nonExistentId) .contentType(MediaType.APPLICATION_JSON) ).andDo(print()); @@ -96,7 +96,7 @@ void t2() throws Exception { void t3() throws Exception { // when ResultActions resultActions = mvc.perform( - get("/api/cocktails") + get("/cocktails") .contentType(MediaType.APPLICATION_JSON) ).andDo(print()); @@ -117,7 +117,7 @@ void t4() throws Exception { // when ResultActions resultActions = mvc.perform( - get("/api/cocktails") + get("/cocktails") .param("lastId", lastId.toString()) .param("size", String.valueOf(size)) .contentType(MediaType.APPLICATION_JSON) From 6afed4462653c417ff5b36a84c46402ebb69c04f Mon Sep 17 00:00:00 2001 From: seungwookc97 Date: Thu, 25 Sep 2025 14:35:11 +0900 Subject: [PATCH 3/3] =?UTF-8?q?refactor:=20security=20=EC=84=A4=EC=A0=95(?= =?UTF-8?q?=EC=9D=BC=EB=8B=A8=20=EA=B0=9C=EB=B0=9C=20=ED=8E=B8=EC=9D=98?= =?UTF-8?q?=EC=84=B1=20=EC=9C=84=ED=95=B4=20permit=20all)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../security/CustomAuthenticationFilter.java | 15 +++++++++----- .../back/global/security/SecurityConfig.java | 20 +++++++++++++++---- 2 files changed, 26 insertions(+), 9 deletions(-) diff --git a/src/main/java/com/back/global/security/CustomAuthenticationFilter.java b/src/main/java/com/back/global/security/CustomAuthenticationFilter.java index ccaff855..062ed8b8 100644 --- a/src/main/java/com/back/global/security/CustomAuthenticationFilter.java +++ b/src/main/java/com/back/global/security/CustomAuthenticationFilter.java @@ -53,8 +53,10 @@ protected void doFilterInternal(HttpServletRequest request, HttpServletResponse private void work(HttpServletRequest request, HttpServletResponse response, FilterChain filterChain) throws ServletException, IOException { String uri = request.getRequestURI(); + String method = request.getMethod(); - // SecurityConfig에서 permitAll()로 설정된 경로들은 필터를 통과시키기 + // 개발 편의성을 위해 모든 요청 통과 (SecurityConfig에서 모든 요청 permitAll) + /* if ( uri.startsWith("/h2-console") || uri.startsWith("/login/oauth2/") || @@ -62,14 +64,17 @@ private void work(HttpServletRequest request, HttpServletResponse response, Filt uri.startsWith("/actuator/") || uri.startsWith("/swagger-ui/") || uri.startsWith("/api-docs/") || - uri.startsWith("/user/") || - uri.startsWith("/cocktails/") || - uri.startsWith("/chatbot/") || - uri.equals("/") + uri.equals("/") || + // 조회 API들 - 권한 불필요 + (method.equals("GET") && uri.startsWith("/cocktails")) || + (method.equals("POST") && uri.equals("/cocktails/search")) || + (method.equals("GET") && uri.startsWith("/posts")) || + (method.equals("GET") && uri.contains("/comments")) ) { filterChain.doFilter(request, response); return; } + */ // 쿠키에서 accessToken 가져오기 String accessToken = rq.getCookieValue("accessToken", ""); diff --git a/src/main/java/com/back/global/security/SecurityConfig.java b/src/main/java/com/back/global/security/SecurityConfig.java index 5f9386cc..b5356587 100644 --- a/src/main/java/com/back/global/security/SecurityConfig.java +++ b/src/main/java/com/back/global/security/SecurityConfig.java @@ -51,21 +51,33 @@ public SecurityFilterChain filterChain(HttpSecurity http) throws Exception { ) // OAuth 인증시 필요할때만 세션 사용 .authorizeHttpRequests(auth -> auth + // 개발 편의성을 위해 모든 요청 허용 + .anyRequest().permitAll() + + /* .requestMatchers("/").permitAll() .requestMatchers("/h2-console/**").permitAll() .requestMatchers("/actuator/**").permitAll() .requestMatchers("/oauth2/**").permitAll() .requestMatchers("/login/oauth2/**").permitAll() .requestMatchers("/swagger-ui/**", "/api-docs/**").permitAll() - .requestMatchers("/user/**").permitAll() - .requestMatchers("/cocktails/**").permitAll() - .requestMatchers("/chatbot/**").permitAll() + + // 권한 불필요 - 조회 API + .requestMatchers(GET, "/cocktails/**").permitAll() + .requestMatchers(POST, "/cocktails/search").permitAll() + .requestMatchers(GET, "/posts").permitAll() + .requestMatchers(GET, "/posts/{postId}").permitAll() + .requestMatchers(GET, "/posts/{postId}/comments").permitAll() + .requestMatchers(GET, "/posts/{postId}/comments/{commentId}").permitAll() + .requestMatchers(GET, "/cocktails/{cocktailId}/comments").permitAll() + .requestMatchers(GET, "/cocktails/{cocktailId}/comments/{cocktailCommentId}").permitAll() // 회원 or 인증된 사용자만 가능 .requestMatchers("/admin/**").hasRole("ADMIN") - //그 외에는 인증해야함 + // 나머지 모든 API는 인증 필요 .anyRequest().authenticated() + */ ) .formLogin(AbstractHttpConfigurer::disable) .httpBasic(AbstractHttpConfigurer::disable)