Skip to content

Commit 6a75ace

Browse files
authored
Merge branch 'main' into Feat/#24
2 parents fc2a409 + c67f9a6 commit 6a75ace

File tree

10 files changed

+57
-32
lines changed

10 files changed

+57
-32
lines changed

src/main/java/com/DecodEat/domain/refreshToken/controller/TokenController.java

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,8 +1,8 @@
11
package com.DecodEat.domain.refreshToken.controller;
22

3-
import com.DecodEat.domain.RefreshToken.dto.request.CreateAccessTokenRequest;
4-
import com.DecodEat.domain.RefreshToken.dto.response.CreateAccessTokenResponse;
5-
import com.DecodEat.domain.RefreshToken.service.TokenService;
3+
import com.DecodEat.domain.refreshToken.dto.request.CreateAccessTokenRequest;
4+
import com.DecodEat.domain.refreshToken.dto.response.CreateAccessTokenResponse;
5+
import com.DecodEat.domain.refreshToken.service.TokenService;
66
import com.DecodEat.global.apiPayload.ApiResponse;
77
import io.swagger.v3.oas.annotations.Operation;
88
import lombok.RequiredArgsConstructor;

src/main/java/com/DecodEat/domain/refreshToken/dto/request/CreateAccessTokenRequest.java

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
package com.DecodEat.domain.RefreshToken.dto.request;
1+
package com.DecodEat.domain.refreshToken.dto.request;
22

33
import lombok.Getter;
44
import lombok.Setter;

src/main/java/com/DecodEat/domain/refreshToken/dto/response/CreateAccessTokenResponse.java

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
package com.DecodEat.domain.RefreshToken.dto.response;
1+
package com.DecodEat.domain.refreshToken.dto.response;
22

33
import lombok.AllArgsConstructor;
44
import lombok.Getter;

src/main/java/com/DecodEat/domain/refreshToken/entity/RefreshToken.java

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
package com.DecodEat.domain.RefreshToken.entity;
1+
package com.DecodEat.domain.refreshToken.entity;
22

33
import jakarta.persistence.*;
44
import lombok.*;

src/main/java/com/DecodEat/domain/refreshToken/repository/RefreshTokenRepository.java

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
1-
package com.DecodEat.domain.RefreshToken.repository;
1+
package com.DecodEat.domain.refreshToken.repository;
22

3-
import com.DecodEat.domain.RefreshToken.entity.RefreshToken;
3+
import com.DecodEat.domain.refreshToken.entity.RefreshToken;
44
import org.springframework.data.jpa.repository.JpaRepository;
55

66
import java.util.Optional;

src/main/java/com/DecodEat/domain/refreshToken/service/RefreshTokenService.java

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
1-
package com.DecodEat.domain.RefreshToken.service;
1+
package com.DecodEat.domain.refreshToken.service;
22

3-
import com.DecodEat.domain.RefreshToken.entity.RefreshToken;
4-
import com.DecodEat.domain.RefreshToken.repository.RefreshTokenRepository;
3+
import com.DecodEat.domain.refreshToken.entity.RefreshToken;
4+
import com.DecodEat.domain.refreshToken.repository.RefreshTokenRepository;
55
import com.DecodEat.global.exception.GeneralException;
66
import lombok.RequiredArgsConstructor;
77
import org.springframework.stereotype.Service;

src/main/java/com/DecodEat/domain/refreshToken/service/TokenService.java

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
package com.DecodEat.domain.RefreshToken.service;
1+
package com.DecodEat.domain.refreshToken.service;
22

33

44
import static com.DecodEat.global.apiPayload.code.status.ErrorStatus.*;
@@ -10,6 +10,7 @@
1010
import lombok.RequiredArgsConstructor;
1111
import org.springframework.stereotype.Service;
1212

13+
1314
import java.time.Duration;
1415

1516
@RequiredArgsConstructor

src/main/java/com/DecodEat/global/config/WebOAuthSecurityConfig.java

Lines changed: 13 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1,26 +1,24 @@
11
package com.DecodEat.global.config;
22

3-
import com.DecodEat.domain.RefreshToken.repository.RefreshTokenRepository;
3+
import com.DecodEat.domain.refreshToken.repository.RefreshTokenRepository;
44
import com.DecodEat.domain.users.service.UserService;
55
import com.DecodEat.global.config.jwt.JwtTokenProvider;
66
import com.DecodEat.global.config.oauth.OAuth2AuthorizationRequestBasedOnCookieRepository;
77
import com.DecodEat.global.config.oauth.OAuth2SuccessHandler;
88
import com.DecodEat.global.config.oauth.OAuth2UserCustomService;
99
import lombok.RequiredArgsConstructor;
10-
import org.springframework.boot.autoconfigure.security.servlet.PathRequest;
1110
import org.springframework.context.annotation.Bean;
1211
import org.springframework.context.annotation.Configuration;
1312
import org.springframework.http.HttpStatus;
1413
import org.springframework.security.config.annotation.web.builders.HttpSecurity;
15-
import org.springframework.security.config.annotation.web.configuration.WebSecurityCustomizer;
1614
import org.springframework.security.config.http.SessionCreationPolicy;
1715
import org.springframework.security.crypto.bcrypt.BCryptPasswordEncoder;
18-
import org.springframework.security.oauth2.client.TokenExchangeOAuth2AuthorizedClientProvider;
1916
import org.springframework.security.web.SecurityFilterChain;
2017
import org.springframework.security.web.authentication.HttpStatusEntryPoint;
2118
import org.springframework.security.web.authentication.UsernamePasswordAuthenticationFilter;
2219
import org.springframework.security.web.util.matcher.AntPathRequestMatcher;
2320
import org.springframework.web.cors.CorsConfigurationSource;
21+
import org.springframework.beans.factory.annotation.Value;
2422

2523
@RequiredArgsConstructor
2624
@Configuration
@@ -31,6 +29,8 @@ public class WebOAuthSecurityConfig {
3129
private final RefreshTokenRepository refreshTokenRepository;
3230
private final UserService userService;
3331
private final CorsConfigurationSource corsConfigurationSource; // CorsCongifuragtinoSource Bean 주입 위함
32+
@Value("${spring.security.oauth2.client.registration.kakao.client-id}")
33+
private String kakaoClientId;
3434

3535
// @Bean
3636
// public WebSecurityCustomizer configure() {
@@ -77,6 +77,15 @@ public SecurityFilterChain securityFilterChain(HttpSecurity http) throws Excepti
7777
.defaultAuthenticationEntryPointFor(
7878
new HttpStatusEntryPoint(HttpStatus.UNAUTHORIZED),
7979
new AntPathRequestMatcher("/api/**")));
80+
// 7. 로그아웃
81+
http.logout(logout -> logout
82+
.logoutUrl("/api/logout")
83+
// 👇 카카오 로그아웃 URL로 리다이렉트
84+
.logoutSuccessUrl("https://kauth.kakao.com/oauth/logout?client_id=" + kakaoClientId + "&logout_redirect_uri=https://decodeat.store.app/")
85+
.invalidateHttpSession(true)
86+
.deleteCookies("JSESSIONID")
87+
.clearAuthentication(true)
88+
);
8089

8190
return http.build();
8291
}

src/main/java/com/DecodEat/global/config/oauth/OAuth2SuccessHandler.java

Lines changed: 14 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
11
package com.DecodEat.global.config.oauth;
22

3-
import com.DecodEat.domain.RefreshToken.entity.RefreshToken;
4-
import com.DecodEat.domain.RefreshToken.repository.RefreshTokenRepository;
3+
import com.DecodEat.domain.refreshToken.entity.RefreshToken;
4+
import com.DecodEat.domain.refreshToken.repository.RefreshTokenRepository;
55
import com.DecodEat.domain.users.entity.User;
66
import com.DecodEat.domain.users.service.UserService;
77
import com.DecodEat.global.config.jwt.JwtTokenProvider;
@@ -24,6 +24,7 @@
2424
public class OAuth2SuccessHandler extends SimpleUrlAuthenticationSuccessHandler {
2525

2626
public static final String REFRESH_TOKEN_COOKIE_NAME = "refresh_token";
27+
public static final String ACCESS_TOKEN_COOKIE_NAME = "access_token";
2728
public static final Duration REFRESH_TOKEN_DURATION = Duration.ofDays(14);
2829
public static final Duration ACCESS_TOKEN_DURATION = Duration.ofHours(1);
2930
public static final String REDIRECT_PATH = "/oauth2/redirect"; // 프론트엔드로 리다이렉트할 경로
@@ -48,8 +49,10 @@ public void onAuthenticationSuccess(HttpServletRequest request, HttpServletRespo
4849
saveRefreshToken(user.getId(), refreshToken);
4950
addRefreshTokenToCookie(request, response, refreshToken);
5051

51-
// 2. 액세스 토큰 생성 -> 리다이렉트 경로에 파라미터로 추가
52+
// 2. 액세스 토큰 생성
5253
String accessToken = tokenProvider.generateToken(user, ACCESS_TOKEN_DURATION);
54+
addAccessTokenToCookie(request, response, accessToken);
55+
5356
String targetUrl = getTargetUrl(accessToken);
5457

5558
// 3. 인증 관련 설정값, 쿠키 제거
@@ -68,6 +71,14 @@ private void saveRefreshToken(Long userId, String newRefreshToken) {
6871
refreshTokenRepository.save(refreshToken);
6972
}
7073

74+
private void addAccessTokenToCookie(HttpServletRequest request, HttpServletResponse response, String accessToken) {
75+
int cookieMaxAge = (int) ACCESS_TOKEN_DURATION.toSeconds();
76+
CookieUtil.deleteCookie(request, response, ACCESS_TOKEN_COOKIE_NAME);
77+
CookieUtil.addCookie(response, ACCESS_TOKEN_COOKIE_NAME, accessToken, cookieMaxAge);
78+
}
79+
80+
81+
7182
// 생성된 리프레시 토큰을 쿠키에 저장
7283
private void addRefreshTokenToCookie(HttpServletRequest request, HttpServletResponse response, String refreshToken) {
7384
int cookieMaxAge = (int) REFRESH_TOKEN_DURATION.toSeconds();

src/main/java/com/DecodEat/global/util/CookieUtil.java

Lines changed: 17 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,7 @@
33
import jakarta.servlet.http.Cookie;
44
import jakarta.servlet.http.HttpServletRequest;
55
import jakarta.servlet.http.HttpServletResponse;
6+
import org.springframework.http.ResponseCookie;
67
import org.springframework.util.SerializationUtils;
78

89
import java.io.*;
@@ -24,15 +25,15 @@ public static Optional<Cookie> getCookie(HttpServletRequest request, String name
2425
}
2526

2627
// 응답 객체(response)에 쿠키를 추가하는 메소드
27-
// httpOnly: true -> 자바스크립트에서 쿠키에 접근 불가
28-
// secure: true -> HTTPS 통신에서만 쿠_cookie 전송
2928
public static void addCookie(HttpServletResponse response, String name, String value, int maxAge) {
30-
Cookie cookie = new Cookie(name, value);
31-
cookie.setPath("/"); // 쿠키가 적용될 경로
32-
cookie.setMaxAge(maxAge); // 쿠키의 유효 기간(초 단위)
33-
cookie.setHttpOnly(true); // JavaScript를 통한 접근 방지
34-
// cookie.setSecure(true); // HTTPS를 사용하는 경우에만 활성화
35-
response.addCookie(cookie);
29+
ResponseCookie cookie = ResponseCookie.from(name, value)
30+
.path("/")
31+
.maxAge(maxAge)
32+
.httpOnly(true)
33+
.secure(true)
34+
.sameSite("None")
35+
.build();
36+
response.addHeader("Set-Cookie", cookie.toString());
3637
}
3738

3839
// 특정 이름의 쿠키를 삭제하는 메소드
@@ -41,10 +42,13 @@ public static void deleteCookie(HttpServletRequest request, HttpServletResponse
4142
if (cookies != null && cookies.length > 0) {
4243
for (Cookie cookie : cookies) {
4344
if (name.equals(cookie.getName())) {
44-
cookie.setValue("");
45-
cookie.setPath("/");
46-
cookie.setMaxAge(0); // 유효 기간을 0으로 설정하여 즉시 만료
47-
response.addCookie(cookie);
45+
ResponseCookie deleteCookie = ResponseCookie.from(name, "")
46+
.path("/")
47+
.maxAge(0)
48+
.secure(true)
49+
.sameSite("None")
50+
.build();
51+
response.addHeader("Set-Cookie", deleteCookie.toString());
4852
}
4953
}
5054
}
@@ -61,4 +65,4 @@ public static <T> T deserialize(Cookie cookie, Class<T> cls) {
6165
byte[] decodedBytes = Base64.getUrlDecoder().decode(cookie.getValue());
6266
return cls.cast(SerializationUtils.deserialize(decodedBytes));
6367
}
64-
}
68+
}

0 commit comments

Comments
 (0)