From 77ee3c5947dce0cae870b896279c90dcd219b146 Mon Sep 17 00:00:00 2001 From: jungdongha Date: Tue, 14 Oct 2025 15:22:51 +0900 Subject: [PATCH 1/2] =?UTF-8?q?refreshtoken=20=EB=B0=9C=EA=B8=89=20?= =?UTF-8?q?=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/controller/AuthController.kt | 19 +++++++++++++++---- .../domain/auth/service/AuthService.kt | 9 ++++++--- 2 files changed, 21 insertions(+), 7 deletions(-) diff --git a/src/main/kotlin/com/back/koreaTravelGuide/domain/auth/controller/AuthController.kt b/src/main/kotlin/com/back/koreaTravelGuide/domain/auth/controller/AuthController.kt index 7312ee4..3d5c64a 100644 --- a/src/main/kotlin/com/back/koreaTravelGuide/domain/auth/controller/AuthController.kt +++ b/src/main/kotlin/com/back/koreaTravelGuide/domain/auth/controller/AuthController.kt @@ -4,9 +4,9 @@ import com.back.koreaTravelGuide.common.ApiResponse import com.back.koreaTravelGuide.common.security.getUserId import com.back.koreaTravelGuide.domain.auth.dto.request.UserRoleUpdateRequest import com.back.koreaTravelGuide.domain.auth.dto.response.AccessTokenResponse -import com.back.koreaTravelGuide.domain.auth.dto.response.LoginResponse import com.back.koreaTravelGuide.domain.auth.service.AuthService import io.swagger.v3.oas.annotations.Operation +import jakarta.servlet.http.Cookie import jakarta.servlet.http.HttpServletRequest import jakarta.servlet.http.HttpServletResponse import org.springframework.beans.factory.annotation.Value @@ -48,10 +48,21 @@ class AuthController( fun updateUserRole( authentication: Authentication, @RequestBody request: UserRoleUpdateRequest, - ): ResponseEntity> { + response: HttpServletResponse, + ): ResponseEntity> { val userId = authentication.getUserId() - val loginResponse = authService.updateRoleAndLogin(userId, request.role) - return ResponseEntity.ok(ApiResponse("역할이 선택되었으며 로그인에 성공했습니다.", loginResponse)) + val (accessToken, refreshToken) = authService.updateRoleAndLogin(userId, request.role) + + val cookie = + Cookie("refreshToken", refreshToken).apply { + isHttpOnly = true + secure = true + path = "/" + maxAge = (refreshTokenExpirationDays * 24 * 60 * 60).toInt() + } + response.addCookie(cookie) + + return ResponseEntity.ok(ApiResponse("역할이 선택되었으며 로그인에 성공했습니다.", AccessTokenResponse(accessToken = accessToken))) } @Operation(summary = "로그아웃") diff --git a/src/main/kotlin/com/back/koreaTravelGuide/domain/auth/service/AuthService.kt b/src/main/kotlin/com/back/koreaTravelGuide/domain/auth/service/AuthService.kt index 74e2092..37c1e74 100644 --- a/src/main/kotlin/com/back/koreaTravelGuide/domain/auth/service/AuthService.kt +++ b/src/main/kotlin/com/back/koreaTravelGuide/domain/auth/service/AuthService.kt @@ -1,7 +1,6 @@ package com.back.koreaTravelGuide.domain.auth.service import com.back.koreaTravelGuide.common.security.JwtTokenProvider -import com.back.koreaTravelGuide.domain.auth.dto.response.LoginResponse import com.back.koreaTravelGuide.domain.user.enums.UserRole import com.back.koreaTravelGuide.domain.user.repository.UserRepository import org.springframework.beans.factory.annotation.Value @@ -22,7 +21,7 @@ class AuthService( fun updateRoleAndLogin( userId: Long, role: UserRole, - ): LoginResponse { + ): Pair { if (role != UserRole.USER && role != UserRole.GUIDE) { throw IllegalArgumentException("선택할 수 없는 역할입니다.") } @@ -39,8 +38,12 @@ class AuthService( userRepository.save(user) val accessToken = jwtTokenProvider.createAccessToken(user.id!!, user.role) + val refreshToken = jwtTokenProvider.createRefreshToken(user.id!!) - return LoginResponse(accessToken = accessToken) + val redisKey = "refreshToken:${user.id}" + redisTemplate.opsForValue().set(redisKey, refreshToken, refreshTokenExpirationDays, TimeUnit.DAYS) + + return Pair(accessToken, refreshToken) } fun logout(accessToken: String) { From 70d24ac028fdea6b143a820ac7909b7c570f517f Mon Sep 17 00:00:00 2001 From: jungdongha Date: Tue, 14 Oct 2025 16:22:21 +0900 Subject: [PATCH 2/2] =?UTF-8?q?logout=20=EB=A1=9C=EC=A7=81=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 --- .../koreaTravelGuide/common/security/JwtAuthenticationFilter.kt | 2 +- .../back/koreaTravelGuide/domain/auth/service/AuthService.kt | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/src/main/kotlin/com/back/koreaTravelGuide/common/security/JwtAuthenticationFilter.kt b/src/main/kotlin/com/back/koreaTravelGuide/common/security/JwtAuthenticationFilter.kt index 4d596e6..5f14bd0 100644 --- a/src/main/kotlin/com/back/koreaTravelGuide/common/security/JwtAuthenticationFilter.kt +++ b/src/main/kotlin/com/back/koreaTravelGuide/common/security/JwtAuthenticationFilter.kt @@ -20,7 +20,7 @@ class JwtAuthenticationFilter( ) { val token = resolveToken(request) - val isBlacklisted = if (token != null) redisTemplate.opsForValue().get(token) != null else false + val isBlacklisted = if (token != null) redisTemplate.opsForValue().get("blacklist:$token") != null else false if (token != null && !isBlacklisted && jwtTokenProvider.validateToken(token)) { val authentication = jwtTokenProvider.getAuthentication(token) diff --git a/src/main/kotlin/com/back/koreaTravelGuide/domain/auth/service/AuthService.kt b/src/main/kotlin/com/back/koreaTravelGuide/domain/auth/service/AuthService.kt index 37c1e74..baa3295 100644 --- a/src/main/kotlin/com/back/koreaTravelGuide/domain/auth/service/AuthService.kt +++ b/src/main/kotlin/com/back/koreaTravelGuide/domain/auth/service/AuthService.kt @@ -50,7 +50,7 @@ class AuthService( val remainingTime = jwtTokenProvider.getRemainingTime(accessToken) if (remainingTime > 0) { - redisTemplate.opsForValue().set(accessToken, "logout", remainingTime, TimeUnit.MILLISECONDS) + redisTemplate.opsForValue().set("blacklist:$accessToken", "logout", remainingTime, TimeUnit.MILLISECONDS) } }