From 27db7e0c236985cdbedd2f85e65aa1cd4a2a9a8c Mon Sep 17 00:00:00 2001 From: shimfff Date: Wed, 19 Feb 2025 18:20:41 +0900 Subject: [PATCH 1/4] =?UTF-8?q?:sparkles:=20feat=20:=20=ED=9A=8C=EC=9B=90?= =?UTF-8?q?=EA=B0=80=EC=9E=85=20=EB=A1=9C=EC=A7=81=20=EC=88=98=EC=A0=95?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../domain/auth/handler/OAuth2SuccessHandler.java | 15 ++++++++++++++- .../domain/auth/service/AuthCommandService.java | 2 ++ .../auth/service/AuthCommandServiceImpl.java | 13 +++++++++++++ .../example/mody/domain/member/entity/Member.java | 4 ++-- 4 files changed, 31 insertions(+), 3 deletions(-) diff --git a/src/main/java/com/example/mody/domain/auth/handler/OAuth2SuccessHandler.java b/src/main/java/com/example/mody/domain/auth/handler/OAuth2SuccessHandler.java index 9909a8d5..1d419882 100644 --- a/src/main/java/com/example/mody/domain/auth/handler/OAuth2SuccessHandler.java +++ b/src/main/java/com/example/mody/domain/auth/handler/OAuth2SuccessHandler.java @@ -4,6 +4,7 @@ import java.net.URLEncoder; import java.nio.charset.StandardCharsets; +import jakarta.servlet.http.Cookie; import org.springframework.beans.factory.annotation.Value; import org.springframework.security.core.Authentication; import org.springframework.security.web.authentication.AuthenticationSuccessHandler; @@ -62,7 +63,19 @@ public void onAuthenticationSuccess(HttpServletRequest request, HttpServletRespo // boolean isNewMember = member.getCreatedAt().equals(member.getUpdatedAt()); // Access Token, Refresh Token 발급 - String newAccessToken = authCommandService.processLoginSuccess(member, response); + String newRefreshToken = authCommandService.processLoginKakaoSuccess(member, response); + + // 쿠키에 저장 + // Refresh Token을 HTTP-Only, Secure 쿠키로 설정 + Cookie refreshTokenCookie = new Cookie("refresh_token", newRefreshToken); + refreshTokenCookie.setHttpOnly(true); // JavaScript 접근 차단 + refreshTokenCookie.setSecure(true); // HTTPS에서만 전송 (로컬 개발 시 false 가능) + refreshTokenCookie.setPath("/"); // 모든 경로에서 사용 가능 + refreshTokenCookie.setMaxAge(7 * 24 * 60 * 60); // 7일 유효기간 설정 + + // SameSite 설정을 위한 헤더 추가 + response.setHeader("Set-Cookie", "refresh_token=" + newRefreshToken + + "; Path=/; HttpOnly; Secure; SameSite=None; Max-Age=" + (7 * 24 * 60 * 60)); String tempUrl = (!member.isRegistrationCompleted()) ? FRONT_SIGNUP_URL : FRONT_HOME_URL; diff --git a/src/main/java/com/example/mody/domain/auth/service/AuthCommandService.java b/src/main/java/com/example/mody/domain/auth/service/AuthCommandService.java index 40aea7f2..4115a6c4 100644 --- a/src/main/java/com/example/mody/domain/auth/service/AuthCommandService.java +++ b/src/main/java/com/example/mody/domain/auth/service/AuthCommandService.java @@ -14,4 +14,6 @@ public interface AuthCommandService { void logout(String refreshToken); String processLoginSuccess(Member member, HttpServletResponse response); + + String processLoginKakaoSuccess(Member member, HttpServletResponse response); } diff --git a/src/main/java/com/example/mody/domain/auth/service/AuthCommandServiceImpl.java b/src/main/java/com/example/mody/domain/auth/service/AuthCommandServiceImpl.java index 4b6455d0..14db2ca8 100644 --- a/src/main/java/com/example/mody/domain/auth/service/AuthCommandServiceImpl.java +++ b/src/main/java/com/example/mody/domain/auth/service/AuthCommandServiceImpl.java @@ -108,4 +108,17 @@ public String processLoginSuccess(Member member, HttpServletResponse response) { return newAccessToken; } + + // 카카오 전용, 리프레시 토큰 발급 + @Override + public String processLoginKakaoSuccess(Member member, HttpServletResponse response) { + // Access Token, Refresh Token 발급 + String newAccessToken = jwtProvider.createAccessToken(member.getId().toString()); + String newRefreshToken = jwtProvider.createRefreshToken(member.getId().toString()); + + // Refresh Token 저장 + saveRefreshToken(member, newRefreshToken); + + return newRefreshToken; + } } diff --git a/src/main/java/com/example/mody/domain/member/entity/Member.java b/src/main/java/com/example/mody/domain/member/entity/Member.java index 175a88c0..9d1a44cd 100644 --- a/src/main/java/com/example/mody/domain/member/entity/Member.java +++ b/src/main/java/com/example/mody/domain/member/entity/Member.java @@ -113,8 +113,8 @@ public class Member extends BaseEntity { @Enumerated(EnumType.STRING) private LoginType loginType; - @Builder.Default - private boolean isRegistrationCompleted = false; // 회원가입 완료 여부 + @Column(columnDefinition = "boolean default false") + private boolean isRegistrationCompleted; // 회원가입 완료 여부 public void completeRegistration(String nickname, LocalDate birthDate, Gender gender, Integer height , String profileImageUrl) { From 63f7941315ee35b75068fe8f846c3bf9e0da30f6 Mon Sep 17 00:00:00 2001 From: jher235 Date: Wed, 19 Feb 2025 18:28:46 +0900 Subject: [PATCH 2/4] =?UTF-8?q?:bug:=20[#141]=20fix:=20=EC=A0=95=EB=A0=AC?= =?UTF-8?q?=20=EC=A1=B0=EA=B1=B4=EC=97=90=20=EB=88=84=EB=9D=BD=EB=90=9C=20?= =?UTF-8?q?=EB=82=B4=EB=A6=BC=EC=B0=A8=EC=88=9C=20=EC=A1=B0=EA=B1=B4=20?= =?UTF-8?q?=EC=9E=91=EC=84=B1?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../domain/bodytype/repository/MemberBodyTypeRepository.java | 1 - .../example/mody/domain/bodytype/service/BodyTypeService.java | 2 +- 2 files changed, 1 insertion(+), 2 deletions(-) diff --git a/src/main/java/com/example/mody/domain/bodytype/repository/MemberBodyTypeRepository.java b/src/main/java/com/example/mody/domain/bodytype/repository/MemberBodyTypeRepository.java index fc398cab..7a9472b8 100644 --- a/src/main/java/com/example/mody/domain/bodytype/repository/MemberBodyTypeRepository.java +++ b/src/main/java/com/example/mody/domain/bodytype/repository/MemberBodyTypeRepository.java @@ -9,7 +9,6 @@ @Repository public interface MemberBodyTypeRepository extends JpaRepository { - Optional findTopByMemberOrderByCreatedAt(Member member); Long countAllByMember(Member member); Optional findTopByMemberOrderByCreatedAtDesc(Member member); } diff --git a/src/main/java/com/example/mody/domain/bodytype/service/BodyTypeService.java b/src/main/java/com/example/mody/domain/bodytype/service/BodyTypeService.java index 3ded547d..151b6626 100644 --- a/src/main/java/com/example/mody/domain/bodytype/service/BodyTypeService.java +++ b/src/main/java/com/example/mody/domain/bodytype/service/BodyTypeService.java @@ -22,7 +22,7 @@ public class BodyTypeService { * @return 마지막 체형 분석이 존재하지 않을 경우 empty Optional을 반환함. */ public Optional findLastBodyType(Member member){ - Optional optionalMemberBodyType = memberBodyTypeRepository.findTopByMemberOrderByCreatedAt(member); + Optional optionalMemberBodyType = memberBodyTypeRepository.findTopByMemberOrderByCreatedAtDesc(member); return optionalMemberBodyType.map(MemberBodyType::getBodyType); } } From c705006ef535a6be34aa1cdc284cdc1c26965bb8 Mon Sep 17 00:00:00 2001 From: shimfff Date: Wed, 19 Feb 2025 18:59:05 +0900 Subject: [PATCH 3/4] =?UTF-8?q?:sparkles:=20feat=20:=20=ED=9A=8C=EC=9B=90?= =?UTF-8?q?=EA=B0=80=EC=9E=85=20=EB=A1=9C=EC=A7=81=20=EC=88=98=EC=A0=95?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../mody/domain/auth/jwt/JwtAuthenticationFilter.java | 9 ++++++--- 1 file changed, 6 insertions(+), 3 deletions(-) diff --git a/src/main/java/com/example/mody/domain/auth/jwt/JwtAuthenticationFilter.java b/src/main/java/com/example/mody/domain/auth/jwt/JwtAuthenticationFilter.java index ea607add..46da073e 100644 --- a/src/main/java/com/example/mody/domain/auth/jwt/JwtAuthenticationFilter.java +++ b/src/main/java/com/example/mody/domain/auth/jwt/JwtAuthenticationFilter.java @@ -46,13 +46,16 @@ protected boolean shouldNotFilter(HttpServletRequest request) throws ServletExce uri = uri.substring(contextPath.length()); } log.info("JwtAuthenticationFilter - Request URI after context removal: {}", uri); - boolean skip = uri.startsWith("/auth/") - && !uri.startsWith("/auth/signup/complete") - && !uri.startsWith("/auth/logout")|| + boolean skip = uri.startsWith("/auth/reissue") || uri.startsWith("/oauth2/") || uri.startsWith("/email/") || uri.startsWith("/swagger-ui/") || uri.startsWith("/v3/api-docs/"); + + skip = (!uri.startsWith("/auth/signup/complete") + && !uri.startsWith("/auth/logout")) && skip; + + log.info("JwtAuthenticationFilter - shouldNotFilter returns: {}", skip); return skip; From 0fc5db185c304881f9b9f51e8c9b7e7c59ef85b1 Mon Sep 17 00:00:00 2001 From: jher235 Date: Wed, 19 Feb 2025 21:18:39 +0900 Subject: [PATCH 4/4] =?UTF-8?q?:bug:=20[#143]=20fix:=20=EA=B8=B0=EC=A1=B4?= =?UTF-8?q?=20=ED=8A=B8=EB=9E=9C=EC=9E=AD=EC=85=98=20=EB=B0=96=EC=97=90?= =?UTF-8?q?=EC=84=9C=20member=EB=A5=BC=20=EC=B0=BE=EC=95=84=EC=84=9C=20?= =?UTF-8?q?=EC=82=AC=EC=9A=A9=ED=95=98=EB=8D=98=20=EB=B0=A9=EC=8B=9D?= =?UTF-8?q?=EC=9D=80=20=EC=98=81=EC=86=8D=EC=84=B1=20=EC=BB=A8=ED=85=8D?= =?UTF-8?q?=EC=8A=A4=ED=8A=B8=EA=B0=80=20member=EB=A5=BC=20=EA=B4=80?= =?UTF-8?q?=EB=A6=AC=ED=95=98=EC=A7=80=20=EB=AA=BB=ED=95=98=EA=B3=A0=20?= =?UTF-8?q?=EC=9E=88=EC=97=88=EA=B8=B0=20=EB=95=8C=EB=AC=B8=EC=97=90=20?= =?UTF-8?q?=EC=88=98=EC=A0=95=20=EC=8B=9C=20=EB=B0=98=EC=98=81=EC=9D=B4=20?= =?UTF-8?q?=EC=95=88=EB=90=A8.=20=EB=94=B0=EB=9D=BC=EC=84=9C=20=EB=A9=94?= =?UTF-8?q?=EC=84=9C=EB=93=9C=20=EB=82=B4=EC=97=90=EC=84=9C=20member?= =?UTF-8?q?=EB=A5=BC=20=EC=B0=BE=EB=8A=94=20=EB=B6=80=EB=B6=84=EC=9D=84=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 --- .../domain/member/service/MemberCommandServiceImpl.java | 7 +++++-- 1 file changed, 5 insertions(+), 2 deletions(-) diff --git a/src/main/java/com/example/mody/domain/member/service/MemberCommandServiceImpl.java b/src/main/java/com/example/mody/domain/member/service/MemberCommandServiceImpl.java index e646218e..1f420751 100644 --- a/src/main/java/com/example/mody/domain/member/service/MemberCommandServiceImpl.java +++ b/src/main/java/com/example/mody/domain/member/service/MemberCommandServiceImpl.java @@ -1,5 +1,7 @@ package com.example.mody.domain.member.service; +import jakarta.persistence.EntityManager; +import lombok.extern.slf4j.Slf4j; import org.springframework.security.crypto.password.PasswordEncoder; import org.springframework.stereotype.Service; import org.springframework.transaction.annotation.Transactional; @@ -27,11 +29,12 @@ public class MemberCommandServiceImpl implements MemberCommandService { private final MemberRepository memberRepository; private final PasswordEncoder passwordEncoder; private final AuthCommandService authCommandService; + private final MemberQueryService memberQueryService; @Override public void completeRegistration(Member member, MemberRegistrationRequest request) { - - member.completeRegistration( + Member unregisteredMember = memberQueryService.findMemberById(member.getId()); // 영속성 컨텍스트가 관리하도록 + unregisteredMember.completeRegistration( request.getNickname(), request.getBirthDate(), request.getGender(),