From dfbc211293fbfba03a8e57d97841607ddcdc7878 Mon Sep 17 00:00:00 2001 From: joona95 Date: Wed, 4 Mar 2026 22:48:19 +0900 Subject: [PATCH 1/2] =?UTF-8?q?fix:=20=ED=83=88=ED=87=B4=20=ED=9B=84=20?= =?UTF-8?q?=EB=A1=9C=EA=B7=B8=EC=9D=B8=20=EB=B6=88=EA=B0=80=20=EC=B2=98?= =?UTF-8?q?=EB=A6=AC?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../com/recipe/app/src/common/config/JwtFilter.java | 12 ++++++++---- .../user/application/CustomUserDetailsService.java | 10 +++++++++- .../recipe/app/src/user/application/UserService.java | 5 +++++ .../recipe/app/src/user/domain/UserWithdrawal.java | 2 +- 4 files changed, 23 insertions(+), 6 deletions(-) diff --git a/src/main/java/com/recipe/app/src/common/config/JwtFilter.java b/src/main/java/com/recipe/app/src/common/config/JwtFilter.java index 11762324..427db954 100644 --- a/src/main/java/com/recipe/app/src/common/config/JwtFilter.java +++ b/src/main/java/com/recipe/app/src/common/config/JwtFilter.java @@ -35,10 +35,14 @@ public void doFilter(ServletRequest request, ServletResponse response, FilterCha if (!StringUtils.hasText(accessToken)) { logger.info("필수 토큰이 없습니다., uri: {}", requestURI); } else if (jwtUtil.isValidAccessToken(accessToken)) { - UserDetails userDetails = userDetailsService.loadUserByUsername(String.valueOf(jwtUtil.getUserId(accessToken))); - Authentication authentication = new UsernamePasswordAuthenticationToken(userDetails, "", userDetails.getAuthorities()); - SecurityContextHolder.getContext().setAuthentication(authentication); - logger.info("Security context에 인증 정보를 저장했습니다, uri: {}", requestURI); + try { + UserDetails userDetails = userDetailsService.loadUserByUsername(String.valueOf(jwtUtil.getUserId(accessToken))); + Authentication authentication = new UsernamePasswordAuthenticationToken(userDetails, "", userDetails.getAuthorities()); + SecurityContextHolder.getContext().setAuthentication(authentication); + logger.info("Security context에 인증 정보를 저장했습니다, uri: {}", requestURI); + } catch (Exception e) { + logger.info("사용자 인증에 실패했습니다. {}, uri: {}", e.getMessage(), requestURI); + } } else { logger.info("유효한 Jwt 토큰이 없습니다, uri: {}", requestURI); } diff --git a/src/main/java/com/recipe/app/src/user/application/CustomUserDetailsService.java b/src/main/java/com/recipe/app/src/user/application/CustomUserDetailsService.java index 7c4d787d..2c37ea8b 100644 --- a/src/main/java/com/recipe/app/src/user/application/CustomUserDetailsService.java +++ b/src/main/java/com/recipe/app/src/user/application/CustomUserDetailsService.java @@ -1,6 +1,7 @@ package com.recipe.app.src.user.application; import com.recipe.app.src.user.domain.SecurityUser; +import com.recipe.app.src.user.domain.User; import org.springframework.security.core.userdetails.UserDetails; import org.springframework.security.core.userdetails.UserDetailsService; import org.springframework.security.core.userdetails.UsernameNotFoundException; @@ -20,6 +21,13 @@ public CustomUserDetailsService(UserService userService) { @Transactional(readOnly = true) @Override public UserDetails loadUserByUsername(String username) throws UsernameNotFoundException { - return new SecurityUser(userService.findByUserId(Long.parseLong(username))); + + User user = userService.findByUserId(Long.parseLong(username)); + + if (user.isDeleted()) { + throw new UsernameNotFoundException("탈퇴한 사용자입니다."); + } + + return new SecurityUser(user); } } diff --git a/src/main/java/com/recipe/app/src/user/application/UserService.java b/src/main/java/com/recipe/app/src/user/application/UserService.java index 0f4c2c4e..4df4cbaf 100644 --- a/src/main/java/com/recipe/app/src/user/application/UserService.java +++ b/src/main/java/com/recipe/app/src/user/application/UserService.java @@ -171,6 +171,11 @@ public UserTokenRefreshResponse reissueToken(UserTokenRefreshRequest request) { throw new UserTokenNotExistException(); } + User user = findByUserId(request.getUserId()); + if (user.isDeleted()) { + throw new UserTokenNotExistException(); + } + return UserTokenRefreshResponse.builder() .userId(request.getUserId()) .accessToken(jwtUtil.createAccessToken(request.getUserId())) diff --git a/src/main/java/com/recipe/app/src/user/domain/UserWithdrawal.java b/src/main/java/com/recipe/app/src/user/domain/UserWithdrawal.java index 90c59c91..ae879c52 100644 --- a/src/main/java/com/recipe/app/src/user/domain/UserWithdrawal.java +++ b/src/main/java/com/recipe/app/src/user/domain/UserWithdrawal.java @@ -27,7 +27,7 @@ public class UserWithdrawal { @Column(name = "userId", nullable = false) private Long userId; - @Column(name = "withdrawalReason", length = 200) + @Column(name = "withdrawalReason") private String withdrawalReason; @Column(name = "createdAt", nullable = false, updatable = false) From 9fd76df6d0bf4e634d1b5c3af8df4aee14558e8d Mon Sep 17 00:00:00 2001 From: joona95 Date: Sun, 8 Mar 2026 23:40:45 +0900 Subject: [PATCH 2/2] =?UTF-8?q?test:=20=ED=86=A0=ED=81=B0=20=EC=9E=AC?= =?UTF-8?q?=EB=B0=9C=EA=B8=89=20=ED=85=8C=EC=8A=A4=ED=8A=B8=20=EC=88=98?= =?UTF-8?q?=EC=A0=95?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../user/application/UserServiceTest.groovy | 33 +++++++++++++++++++ 1 file changed, 33 insertions(+) diff --git a/src/test/groovy/com/recipe/app/src/user/application/UserServiceTest.groovy b/src/test/groovy/com/recipe/app/src/user/application/UserServiceTest.groovy index fc89fa67..44a25b10 100644 --- a/src/test/groovy/com/recipe/app/src/user/application/UserServiceTest.groovy +++ b/src/test/groovy/com/recipe/app/src/user/application/UserServiceTest.groovy @@ -420,12 +420,19 @@ class UserServiceTest extends Specification { def "토큰 재발급"() { given: + User user = User.builder() + .userId(1) + .socialId("naver_1") + .nickname("테스터1") + .build() + UserTokenRefreshRequest request = UserTokenRefreshRequest.builder() .userId(1) .refreshToken("refresh_token") .build() jwtUtil.isValidRefreshToken(request.refreshToken) >> true + userRepository.findById(request.userId) >> Optional.of(user) String accessToken = "new_access_token" String refreshToken = "new_refresh_token" @@ -458,4 +465,30 @@ class UserServiceTest extends Specification { def e = thrown(UserTokenNotExistException.class) e.message == "유효하지 않은 JWT입니다." } + + def "토큰 재발급 시 탈퇴한 사용자이면 예외 발생"() { + + given: + User user = User.builder() + .userId(1) + .socialId("naver_1") + .nickname("테스터1") + .build() + user.markAsDeleted() + + UserTokenRefreshRequest request = UserTokenRefreshRequest.builder() + .userId(1) + .refreshToken("refresh_token") + .build() + + jwtUtil.isValidRefreshToken(request.refreshToken) >> true + userRepository.findById(request.userId) >> Optional.of(user) + + when: + userService.reissueToken(request) + + then: + def e = thrown(UserTokenNotExistException.class) + e.message == "유효하지 않은 JWT입니다." + } }