Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view

This file was deleted.

Large diffs are not rendered by default.

Original file line number Diff line number Diff line change
@@ -0,0 +1,20 @@
package com.ai.lawyer.domain.member.dto;

import lombok.Builder;
import lombok.Getter;

@Getter
@Builder
public class LogoutResponse {
private boolean success;
private String message;
private String oauth2LogoutUrl; // OAuth2 제공자 로그아웃 URL (없으면 null)

public static LogoutResponse of(String oauth2LogoutUrl) {
return LogoutResponse.builder()
.success(true)
.message("로그아웃 성공")
.oauth2LogoutUrl(oauth2LogoutUrl)
.build();
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -152,13 +152,6 @@ public MemberResponse refreshToken(String refreshToken, HttpServletResponse resp
return MemberResponse.from(member);
}

@Transactional
public void withdraw(Long memberId) {
Member member = memberRepository.findById(memberId)
.orElseThrow(() -> new IllegalArgumentException(ERR_MEMBER_NOT_FOUND));

memberRepository.delete(member);
}

public MemberResponse getMemberById(Long memberId) {
// Member 또는 OAuth2Member 조회
Expand All @@ -175,6 +168,44 @@ public MemberResponse getMemberById(Long memberId) {
return MemberResponse.from(member);
}

public String getLoginIdByMemberId(Long memberId) {
// Member 또는 OAuth2Member 조회
com.ai.lawyer.domain.member.entity.MemberAdapter member = memberRepository.findById(memberId).orElse(null);

if (member == null && oauth2MemberRepository != null) {
member = oauth2MemberRepository.findById(memberId).orElse(null);
}

if (member == null) {
log.warn("회원을 찾을 수 없습니다: memberId={}", memberId);
return null;
}

return member.getLoginId();
}

@Transactional
public void deleteMember(String loginId) {
// Member 또는 OAuth2Member 삭제
java.util.Optional<Member> regularMember = memberRepository.findByLoginId(loginId);
if (regularMember.isPresent()) {
memberRepository.delete(regularMember.get());
log.info("일반 회원 삭제 완료: loginId={}", loginId);
return;
}

if (oauth2MemberRepository != null) {
java.util.Optional<OAuth2Member> oauth2Member = oauth2MemberRepository.findByLoginId(loginId);
if (oauth2Member.isPresent()) {
oauth2MemberRepository.delete(oauth2Member.get());
log.info("OAuth2 회원 삭제 완료: loginId={}", loginId);
return;
}
}

log.warn("삭제할 회원을 찾을 수 없습니다: loginId={}", loginId);
}

public void sendCodeToEmailByLoginId(String loginId) {
Member member = memberRepository.findByLoginId(loginId)
.orElseThrow(() -> new IllegalArgumentException(ERR_MEMBER_NOT_FOUND_BY_LOGIN_ID));
Expand Down
37 changes: 21 additions & 16 deletions backend/src/main/java/com/ai/lawyer/global/jwt/CookieUtil.java
Original file line number Diff line number Diff line change
Expand Up @@ -3,8 +3,11 @@
import jakarta.servlet.http.Cookie;
import jakarta.servlet.http.HttpServletRequest;
import jakarta.servlet.http.HttpServletResponse;
import org.springframework.http.ResponseCookie;
import org.springframework.stereotype.Component;

import java.time.Duration;

@Component
public class CookieUtil {

Expand All @@ -15,13 +18,14 @@ public class CookieUtil {
// 쿠키 만료 시간 상수 (초 단위)
private static final int MINUTES_PER_HOUR = 60;
private static final int HOURS_PER_DAY = 24;
private static final int ACCESS_TOKEN_EXPIRE_TIME = 5 * MINUTES_PER_HOUR; // 5분
private static final int ACCESS_TOKEN_EXPIRE_TIME = 5 * 60; // 5분 (300초)
private static final int REFRESH_TOKEN_EXPIRE_TIME = 7 * HOURS_PER_DAY * MINUTES_PER_HOUR * 60; // 7일

// 쿠키 보안 설정 상수
private static final boolean HTTP_ONLY = true;
private static final boolean SECURE_IN_PRODUCTION = false; // 운영환경에서는 true로 변경 (HTTPS)
private static final boolean SECURE_IN_PRODUCTION = true; // 운영환경에서는 true로 변경 (HTTPS)
private static final String COOKIE_PATH = "/";
private static final String SAME_SITE = "None"; // None, Lax, Strict 중 선택
private static final int COOKIE_EXPIRE_IMMEDIATELY = 0;

public void setTokenCookies(HttpServletResponse response, String accessToken, String refreshToken) {
Expand All @@ -30,13 +34,13 @@ public void setTokenCookies(HttpServletResponse response, String accessToken, St
}

public void setAccessTokenCookie(HttpServletResponse response, String accessToken) {
Cookie accessCookie = createCookie(ACCESS_TOKEN_NAME, accessToken, ACCESS_TOKEN_EXPIRE_TIME);
response.addCookie(accessCookie);
ResponseCookie cookie = createResponseCookie(ACCESS_TOKEN_NAME, accessToken, ACCESS_TOKEN_EXPIRE_TIME);
response.addHeader("Set-Cookie", cookie.toString());
}

public void setRefreshTokenCookie(HttpServletResponse response, String refreshToken) {
Cookie refreshCookie = createCookie(REFRESH_TOKEN_NAME, refreshToken, REFRESH_TOKEN_EXPIRE_TIME);
response.addCookie(refreshCookie);
ResponseCookie cookie = createResponseCookie(REFRESH_TOKEN_NAME, refreshToken, REFRESH_TOKEN_EXPIRE_TIME);
response.addHeader("Set-Cookie", cookie.toString());
}

public void clearTokenCookies(HttpServletResponse response) {
Expand All @@ -45,23 +49,24 @@ public void clearTokenCookies(HttpServletResponse response) {
}

/**
* 쿠키를 생성합니다.
* ResponseCookie를 생성합니다 (SameSite 지원).
*/
private Cookie createCookie(String name, String value, int maxAge) {
Cookie cookie = new Cookie(name, value);
cookie.setHttpOnly(HTTP_ONLY);
cookie.setSecure(SECURE_IN_PRODUCTION);
cookie.setPath(COOKIE_PATH);
cookie.setMaxAge(maxAge);
return cookie;
private ResponseCookie createResponseCookie(String name, String value, int maxAge) {
return ResponseCookie.from(name, value)
.httpOnly(HTTP_ONLY)
.secure(SECURE_IN_PRODUCTION)
.path(COOKIE_PATH)
.maxAge(Duration.ofSeconds(maxAge))
.sameSite(SAME_SITE)
.build();
}

/**
* 쿠키를 삭제합니다 (MaxAge를 0으로 설정).
*/
private void clearCookie(HttpServletResponse response, String cookieName) {
Cookie cookie = createCookie(cookieName, null, COOKIE_EXPIRE_IMMEDIATELY);
response.addCookie(cookie);
ResponseCookie cookie = createResponseCookie(cookieName, "", COOKIE_EXPIRE_IMMEDIATELY);
response.addHeader("Set-Cookie", cookie.toString());
}

public String getAccessTokenFromCookies(HttpServletRequest request) {
Expand Down
Loading