From 52a9f7a1a0cbdcde1188a057096db645df75da1a Mon Sep 17 00:00:00 2001 From: kang Date: Tue, 20 Aug 2024 05:39:11 +0900 Subject: [PATCH 01/12] chore: add msg for refreshed access token api --- src/main/java/co/orange/ddanzi/common/error/Error.java | 2 ++ .../java/co/orange/ddanzi/common/response/Success.java | 9 ++++++--- 2 files changed, 8 insertions(+), 3 deletions(-) diff --git a/src/main/java/co/orange/ddanzi/common/error/Error.java b/src/main/java/co/orange/ddanzi/common/error/Error.java index 07ecbcbf..f671a2cc 100644 --- a/src/main/java/co/orange/ddanzi/common/error/Error.java +++ b/src/main/java/co/orange/ddanzi/common/error/Error.java @@ -12,6 +12,7 @@ public enum Error { ERROR(HttpStatus.BAD_REQUEST, "Request processing failed"), // 400 BAD REQUEST + REFRESH_TOKEN_IS_NULL(HttpStatus.BAD_REQUEST, "Refresh token is null"), ACCOUNT_NAME_DOES_NOT_MATCH(HttpStatus.BAD_REQUEST, "The account name does not match to user name."), DUE_DATE_IS_INCORRECT(HttpStatus.BAD_REQUEST, "The due date is incorrect."), ITEM_IS_NOT_ON_SALE(HttpStatus.BAD_REQUEST, "The item is not on sale."), @@ -24,6 +25,7 @@ public enum Error { INVALID_JWT_EXCEPTION(HttpStatus.UNAUTHORIZED, "Invalid JWT"), LOG_OUT_JWT_TOKEN(HttpStatus.UNAUTHORIZED,"Logged out user"), JWT_EXPIRED(HttpStatus.UNAUTHORIZED,"JWT expired"), + REFRESH_TOKEN_EXPIRED(HttpStatus.UNAUTHORIZED,"Refresh Token expired"), JWT_TOKEN_NOT_EXISTS(HttpStatus.UNAUTHORIZED,"JWT value does not exist in header"), diff --git a/src/main/java/co/orange/ddanzi/common/response/Success.java b/src/main/java/co/orange/ddanzi/common/response/Success.java index bd909f7c..32bf7638 100644 --- a/src/main/java/co/orange/ddanzi/common/response/Success.java +++ b/src/main/java/co/orange/ddanzi/common/response/Success.java @@ -13,9 +13,6 @@ public enum Success { SUCCESS(HttpStatus.OK, "Request successfully processed."), // 200 OK SUCCESS - SIGNIN_KAKAO_SUCCESS(HttpStatus.CREATED, "Successfully sign in using Kakao"), - SIGNIN_APPLE_SUCCESS(HttpStatus.CREATED, "Successfully sign in using Kakao"), - GET_REDIS_KEY_SUCCESS(HttpStatus.CREATED, "Successfully retrieved the redis key"), GET_HOME_INFO_SUCCESS(HttpStatus.OK, "Successfully retrieved home information."), @@ -52,8 +49,14 @@ public enum Success { // 201 CREATED + SIGNIN_KAKAO_SUCCESS(HttpStatus.CREATED, "Successfully sign in using Kakao"), + SIGNIN_APPLE_SUCCESS(HttpStatus.CREATED, "Successfully sign in using Kakao"), + + REFRESH_ACCESS_TOKEN_SUCCESS(HttpStatus.CREATED, "Successfully refreshed access token."), + SET_REDIS_KEY_SUCCESS(HttpStatus.CREATED, "Successfully set the redis key"), + CREATE_AUTHENTICATION_SUCCESS(HttpStatus.CREATED, "Successfully verified identity."), CREATE_PRODUCT_SUCCESS(HttpStatus.CREATED, "Successfully confirmed the product."), CREATE_PAYMENT_SUCCESS(HttpStatus.CREATED, "Successfully registered payment information."), From a068db7eeb3ba2d5880b6f85216eb6cf1ac68009 Mon Sep 17 00:00:00 2001 From: kang Date: Tue, 20 Aug 2024 05:39:21 +0900 Subject: [PATCH 02/12] feat: create refreshed access token api --- .../ddanzi/controller/AuthController.java | 5 +++++ .../co/orange/ddanzi/global/jwt/JwtUtils.java | 22 +++++++++++++++++++ .../ddanzi/service/auth/OAuthService.java | 19 ++++++++++++++++ 3 files changed, 46 insertions(+) diff --git a/src/main/java/co/orange/ddanzi/controller/AuthController.java b/src/main/java/co/orange/ddanzi/controller/AuthController.java index 2a982168..3aea47fd 100644 --- a/src/main/java/co/orange/ddanzi/controller/AuthController.java +++ b/src/main/java/co/orange/ddanzi/controller/AuthController.java @@ -32,6 +32,11 @@ ApiResponse signin(@RequestBody SigninRequestDto requestDto) throws JsonProce return oAuthService.kakaoSignIn(requestDto.getToken()); } + @PostMapping("/refreshtoken") + ApiResponse refreshAccessToken(@RequestBody String refreshToken) throws JsonProcessingException{ + return oAuthService.refreshAccessToken(refreshToken); + } + @PostMapping("/verification") ApiResponse verify(@RequestBody VerifyRequestDto requestDto) { return authService.verify(requestDto); diff --git a/src/main/java/co/orange/ddanzi/global/jwt/JwtUtils.java b/src/main/java/co/orange/ddanzi/global/jwt/JwtUtils.java index b70bdf4d..c45691cf 100644 --- a/src/main/java/co/orange/ddanzi/global/jwt/JwtUtils.java +++ b/src/main/java/co/orange/ddanzi/global/jwt/JwtUtils.java @@ -117,6 +117,15 @@ public boolean validateToken(String token) { } } + public boolean isValidRefreshToken(String email, String refreshToken) { + if (email == null) { + return false; // 이메일이 null인 경우 유효하지 않음 + } + String storedRefreshToken = stringRedisTemplate.opsForValue().get(email); + return refreshToken.equals(storedRefreshToken); + } + + public boolean validateTokenInLogoutPage(String token) { if (!StringUtils.hasText(token)) { return false; @@ -146,6 +155,19 @@ public String getIdTokenFromToken(String token) { return getClaims(token).get("email").toString(); } + public String getIdFromRefreshToken(String token) { + try { + Claims claims = Jwts.parser() + .setSigningKey(jwtSecretKey) + .parseClaimsJws(token) + .getBody(); + return claims.get("email").toString(); // 이메일 정보 반환 + } catch (Exception e) { + // 토큰이 유효하지 않거나 에러 발생 시 null 반환 + return null; + } + } + public Claims getClaims(String token) { return Jwts.parser().setSigningKey(jwtSecretKey).parseClaimsJws(token).getBody(); diff --git a/src/main/java/co/orange/ddanzi/service/auth/OAuthService.java b/src/main/java/co/orange/ddanzi/service/auth/OAuthService.java index 4a2dccce..83ec75ad 100644 --- a/src/main/java/co/orange/ddanzi/service/auth/OAuthService.java +++ b/src/main/java/co/orange/ddanzi/service/auth/OAuthService.java @@ -1,5 +1,6 @@ package co.orange.ddanzi.service.auth; +import co.orange.ddanzi.common.error.Error; import co.orange.ddanzi.domain.user.User; import co.orange.ddanzi.domain.user.enums.LoginType; import co.orange.ddanzi.domain.user.enums.UserStatus; @@ -26,6 +27,7 @@ import java.io.IOException; import java.io.InputStreamReader; import java.util.List; +import java.util.Map; import java.util.Optional; import java.util.Random; import java.util.stream.Collectors; @@ -61,6 +63,23 @@ public ApiResponse kakaoSignIn(String token) throws JsonProcessingException { return ApiResponse.onSuccess(Success.SIGNIN_KAKAO_SUCCESS, responseDto); } + @Transactional + public ApiResponse refreshAccessToken(String refreshToken) throws JsonProcessingException { + if (refreshToken == null || refreshToken.isEmpty()) { + return ApiResponse.onFailure(Error.REFRESH_TOKEN_IS_NULL, Map.of("refreshtoken", refreshToken)); + } + + String email = jwtUtils.getIdTokenFromToken(refreshToken); + + if (!jwtUtils.isValidRefreshToken(email, refreshToken)) { + return ApiResponse.onFailure(Error.REFRESH_TOKEN_EXPIRED, Map.of("refreshtoken", refreshToken)); + } + + String newAccessToken = jwtUtils.createAccessToken(email); + + return ApiResponse.onSuccess(Success.REFRESH_ACCESS_TOKEN_SUCCESS, Map.of("accesstoken",newAccessToken )); + } + public void kakaoSignUp(String email) { User user = User.builder() .email(email) From f71305f944bc74f88bcb7df2fd02811d84b7fe8f Mon Sep 17 00:00:00 2001 From: kang Date: Tue, 20 Aug 2024 05:48:22 +0900 Subject: [PATCH 03/12] chore: modify response dto of test signin api --- src/main/java/co/orange/ddanzi/service/auth/AuthService.java | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/src/main/java/co/orange/ddanzi/service/auth/AuthService.java b/src/main/java/co/orange/ddanzi/service/auth/AuthService.java index 9a425983..35512cf7 100644 --- a/src/main/java/co/orange/ddanzi/service/auth/AuthService.java +++ b/src/main/java/co/orange/ddanzi/service/auth/AuthService.java @@ -3,7 +3,7 @@ import co.orange.ddanzi.domain.user.Authentication; import co.orange.ddanzi.domain.user.User; import co.orange.ddanzi.domain.user.enums.UserStatus; -import co.orange.ddanzi.dto.auth.AuthResponseDto; +import co.orange.ddanzi.dto.auth.SigninResponseDto; import co.orange.ddanzi.dto.auth.VerifyRequestDto; import co.orange.ddanzi.dto.auth.VerifyResponseDto; import co.orange.ddanzi.common.error.Error; @@ -39,8 +39,9 @@ public ApiResponse testSignin(String idToken){ } User user = optionalUser.get(); - AuthResponseDto responseDto = AuthResponseDto.builder() + SigninResponseDto responseDto = SigninResponseDto.builder() .accesstoken(jwtUtils.createAccessToken(user.getEmail())) + .refreshtoken(jwtUtils.createRefreshToken(user.getEmail())) .nickname(user.getNickname()) .build(); return ApiResponse.onSuccess(Success.SUCCESS, responseDto); From bfcb099d7ce1836b1f267a1c83a6b2cc49951b79 Mon Sep 17 00:00:00 2001 From: kang Date: Tue, 20 Aug 2024 05:48:47 +0900 Subject: [PATCH 04/12] feat: set request body of refreshed access token api --- .../java/co/orange/ddanzi/controller/AuthController.java | 5 +++-- .../co/orange/ddanzi/dto/auth/RefreshTokenRequestDto.java | 8 ++++++++ 2 files changed, 11 insertions(+), 2 deletions(-) create mode 100644 src/main/java/co/orange/ddanzi/dto/auth/RefreshTokenRequestDto.java diff --git a/src/main/java/co/orange/ddanzi/controller/AuthController.java b/src/main/java/co/orange/ddanzi/controller/AuthController.java index 3aea47fd..4e347d81 100644 --- a/src/main/java/co/orange/ddanzi/controller/AuthController.java +++ b/src/main/java/co/orange/ddanzi/controller/AuthController.java @@ -1,6 +1,7 @@ package co.orange.ddanzi.controller; import co.orange.ddanzi.domain.user.enums.LoginType; +import co.orange.ddanzi.dto.auth.RefreshTokenRequestDto; import co.orange.ddanzi.dto.auth.SigninRequestDto; import co.orange.ddanzi.dto.auth.VerifyRequestDto; import co.orange.ddanzi.common.response.ApiResponse; @@ -33,8 +34,8 @@ ApiResponse signin(@RequestBody SigninRequestDto requestDto) throws JsonProce } @PostMapping("/refreshtoken") - ApiResponse refreshAccessToken(@RequestBody String refreshToken) throws JsonProcessingException{ - return oAuthService.refreshAccessToken(refreshToken); + ApiResponse refreshAccessToken(@RequestBody RefreshTokenRequestDto requestDto) throws JsonProcessingException{ + return oAuthService.refreshAccessToken(requestDto.getRefreshtoken()); } @PostMapping("/verification") diff --git a/src/main/java/co/orange/ddanzi/dto/auth/RefreshTokenRequestDto.java b/src/main/java/co/orange/ddanzi/dto/auth/RefreshTokenRequestDto.java new file mode 100644 index 00000000..6a43e950 --- /dev/null +++ b/src/main/java/co/orange/ddanzi/dto/auth/RefreshTokenRequestDto.java @@ -0,0 +1,8 @@ +package co.orange.ddanzi.dto.auth; + +import lombok.Getter; + +@Getter +public class RefreshTokenRequestDto { + private String refreshtoken; +} From 77e9d796762bcf4bb1e171e26c5bbbe4dc251f23 Mon Sep 17 00:00:00 2001 From: kang Date: Tue, 20 Aug 2024 05:49:06 +0900 Subject: [PATCH 05/12] feat: add permit list --- .../java/co/orange/ddanzi/global/security/SecurityConfig.java | 1 + 1 file changed, 1 insertion(+) diff --git a/src/main/java/co/orange/ddanzi/global/security/SecurityConfig.java b/src/main/java/co/orange/ddanzi/global/security/SecurityConfig.java index 41f8d51a..f342702d 100644 --- a/src/main/java/co/orange/ddanzi/global/security/SecurityConfig.java +++ b/src/main/java/co/orange/ddanzi/global/security/SecurityConfig.java @@ -21,6 +21,7 @@ public class SecurityConfig { private String[] permitList = { "/api/v1/auth/signin", "/api/v1/auth/signin/test", + "/api/v1/auth/refreshtoken", "/api/v1/home/**", "/api/v1/search/**" }; From 0986cf1e04ca29ebc991f12252fc0bae80ca6e08 Mon Sep 17 00:00:00 2001 From: kang Date: Tue, 20 Aug 2024 06:06:34 +0900 Subject: [PATCH 06/12] feat: add toJson method --- .../co/orange/ddanzi/common/error/ErrorResponse.java | 11 +++++++++++ 1 file changed, 11 insertions(+) diff --git a/src/main/java/co/orange/ddanzi/common/error/ErrorResponse.java b/src/main/java/co/orange/ddanzi/common/error/ErrorResponse.java index c3cd61db..8eb9b300 100644 --- a/src/main/java/co/orange/ddanzi/common/error/ErrorResponse.java +++ b/src/main/java/co/orange/ddanzi/common/error/ErrorResponse.java @@ -1,6 +1,8 @@ package co.orange.ddanzi.common.error; import co.orange.ddanzi.global.handler.GlobalControllerHandler; +import com.fasterxml.jackson.core.JsonProcessingException; +import com.fasterxml.jackson.databind.ObjectMapper; import jakarta.servlet.http.HttpServletRequest; import lombok.*; @@ -45,4 +47,13 @@ public static ErrorResponse onFailure(Error error, String message) { .build(); } + public String toJson() { + ObjectMapper objectMapper = new ObjectMapper(); + try { + return objectMapper.writeValueAsString(this); + } catch (JsonProcessingException e) { + return "{\"message\":\"JSON 변환 오류\", \"code\":500}"; + } + } + } \ No newline at end of file From 4937ce5c2eddc430d952b609abc27fee515555f1 Mon Sep 17 00:00:00 2001 From: kang Date: Tue, 20 Aug 2024 06:06:51 +0900 Subject: [PATCH 07/12] chore: delete unused code --- .../co/orange/ddanzi/global/handler/GlobalExceptionHandler.java | 2 -- 1 file changed, 2 deletions(-) diff --git a/src/main/java/co/orange/ddanzi/global/handler/GlobalExceptionHandler.java b/src/main/java/co/orange/ddanzi/global/handler/GlobalExceptionHandler.java index 9e7ff825..5b4d725a 100644 --- a/src/main/java/co/orange/ddanzi/global/handler/GlobalExceptionHandler.java +++ b/src/main/java/co/orange/ddanzi/global/handler/GlobalExceptionHandler.java @@ -6,7 +6,6 @@ import jakarta.servlet.http.HttpServletRequest; import lombok.RequiredArgsConstructor; import lombok.extern.slf4j.Slf4j; -import org.springframework.core.annotation.Order; import org.springframework.http.ResponseEntity; import org.springframework.web.bind.annotation.ControllerAdvice; import org.springframework.web.bind.annotation.ExceptionHandler; @@ -14,7 +13,6 @@ import static org.springframework.http.HttpStatus.INTERNAL_SERVER_ERROR; -@Order(1) @ControllerAdvice @Slf4j @RequiredArgsConstructor From 7cd6e9b4d67af6c9b84f77bf4af9eab835ff7baa Mon Sep 17 00:00:00 2001 From: kang Date: Tue, 20 Aug 2024 06:07:28 +0900 Subject: [PATCH 08/12] chore: add catch exception --- .../orange/ddanzi/global/jwt/JwtFilter.java | 26 +++++++++++++------ 1 file changed, 18 insertions(+), 8 deletions(-) diff --git a/src/main/java/co/orange/ddanzi/global/jwt/JwtFilter.java b/src/main/java/co/orange/ddanzi/global/jwt/JwtFilter.java index a1616879..1b3e9966 100644 --- a/src/main/java/co/orange/ddanzi/global/jwt/JwtFilter.java +++ b/src/main/java/co/orange/ddanzi/global/jwt/JwtFilter.java @@ -1,11 +1,14 @@ package co.orange.ddanzi.global.jwt; +import co.orange.ddanzi.common.error.ErrorResponse; +import co.orange.ddanzi.common.exception.UnauthorizedException; import jakarta.servlet.FilterChain; import jakarta.servlet.ServletException; import jakarta.servlet.http.HttpServletRequest; import jakarta.servlet.http.HttpServletResponse; import lombok.RequiredArgsConstructor; import lombok.extern.slf4j.Slf4j; +import org.springframework.http.HttpStatus; import org.springframework.security.core.Authentication; import org.springframework.security.core.context.SecurityContextHolder; import org.springframework.web.filter.OncePerRequestFilter; @@ -22,15 +25,22 @@ protected void doFilterInternal(HttpServletRequest request, HttpServletResponse String token = jwtUtils.resolveJWT(request); log.info("Request to {}: token={}", request.getRequestURI(), token); - //home & search api - if(isHomeOrSearchRequest(request.getRequestURI())){ - handleHomeOrSearchRequest(token); + try { + //home & search api + if (isHomeOrSearchRequest(request.getRequestURI())) { + handleHomeOrSearchRequest(token); + } + //other api + else { + handleGeneralRequest(token); + } + filterChain.doFilter(request, response); + } catch (UnauthorizedException e) { + log.error("Unauthorized Exception: {}", e.getMessage()); + response.setStatus(HttpStatus.UNAUTHORIZED.value()); + response.setContentType("application/json"); + response.getWriter().write(ErrorResponse.onFailure(e.getError()).toJson()); } - //other api - else { - handleGeneralRequest(token); - } - filterChain.doFilter(request, response); } @Override From 02504df7b95d93a815f1fbc0008309b5fb2bb61c Mon Sep 17 00:00:00 2001 From: kang Date: Tue, 20 Aug 2024 06:07:55 +0900 Subject: [PATCH 09/12] chore: get request from RequestContextHolder --- .../ddanzi/global/handler/GlobalControllerHandler.java | 8 +++++--- 1 file changed, 5 insertions(+), 3 deletions(-) diff --git a/src/main/java/co/orange/ddanzi/global/handler/GlobalControllerHandler.java b/src/main/java/co/orange/ddanzi/global/handler/GlobalControllerHandler.java index 4b85abd4..4494a624 100644 --- a/src/main/java/co/orange/ddanzi/global/handler/GlobalControllerHandler.java +++ b/src/main/java/co/orange/ddanzi/global/handler/GlobalControllerHandler.java @@ -3,17 +3,19 @@ import jakarta.servlet.http.HttpServletRequest; import org.springframework.web.bind.annotation.ControllerAdvice; import org.springframework.web.bind.annotation.ModelAttribute; +import org.springframework.web.context.request.RequestContextHolder; +import org.springframework.web.context.request.ServletRequestAttributes; @ControllerAdvice public class GlobalControllerHandler { - private static final ThreadLocal requestHolder = new ThreadLocal<>(); @ModelAttribute public void setRequest(HttpServletRequest request) { - requestHolder.set(request); + RequestContextHolder.setRequestAttributes(new ServletRequestAttributes(request)); } public static HttpServletRequest getRequest() { - return requestHolder.get(); + ServletRequestAttributes attributes = (ServletRequestAttributes) RequestContextHolder.getRequestAttributes(); + return attributes != null ? attributes.getRequest() : null; } } From 0dc0f7a759d0ffb5616221198e107f8ce88eaa7d Mon Sep 17 00:00:00 2001 From: kang Date: Tue, 20 Aug 2024 06:10:43 +0900 Subject: [PATCH 10/12] chore: change getIdFromToken to getIdFromRefreshToken --- src/main/java/co/orange/ddanzi/service/auth/OAuthService.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/main/java/co/orange/ddanzi/service/auth/OAuthService.java b/src/main/java/co/orange/ddanzi/service/auth/OAuthService.java index 83ec75ad..204adcc5 100644 --- a/src/main/java/co/orange/ddanzi/service/auth/OAuthService.java +++ b/src/main/java/co/orange/ddanzi/service/auth/OAuthService.java @@ -69,7 +69,7 @@ public ApiResponse refreshAccessToken(String refreshToken) throws JsonProcess return ApiResponse.onFailure(Error.REFRESH_TOKEN_IS_NULL, Map.of("refreshtoken", refreshToken)); } - String email = jwtUtils.getIdTokenFromToken(refreshToken); + String email = jwtUtils.getIdFromRefreshToken(refreshToken); if (!jwtUtils.isValidRefreshToken(email, refreshToken)) { return ApiResponse.onFailure(Error.REFRESH_TOKEN_EXPIRED, Map.of("refreshtoken", refreshToken)); From 75fd092173c20cf80cbbfda4bbf4ec32eaa60a19 Mon Sep 17 00:00:00 2001 From: kang Date: Tue, 20 Aug 2024 06:38:07 +0900 Subject: [PATCH 11/12] feat: create logout api --- .../ddanzi/common/response/Success.java | 1 + .../ddanzi/controller/AuthController.java | 25 ++++++++++++++++--- .../co/orange/ddanzi/global/jwt/JwtUtils.java | 12 +++++++-- 3 files changed, 32 insertions(+), 6 deletions(-) diff --git a/src/main/java/co/orange/ddanzi/common/response/Success.java b/src/main/java/co/orange/ddanzi/common/response/Success.java index 32bf7638..0403f90c 100644 --- a/src/main/java/co/orange/ddanzi/common/response/Success.java +++ b/src/main/java/co/orange/ddanzi/common/response/Success.java @@ -46,6 +46,7 @@ public enum Success { DELETE_INTEREST_SUCCESS(HttpStatus.OK, "Successfully removed the product from interest List."), DELETE_ADDRESS_SUCCESS(HttpStatus.OK, "Successfully deleted the delivery address."), DELETE_ACCOUNT_SUCCESS(HttpStatus.OK, "Successfully deleted the account"), + LOGOUT_SUCCESS(HttpStatus.OK, "Successfully log out the user"), // 201 CREATED diff --git a/src/main/java/co/orange/ddanzi/controller/AuthController.java b/src/main/java/co/orange/ddanzi/controller/AuthController.java index 4e347d81..20f23284 100644 --- a/src/main/java/co/orange/ddanzi/controller/AuthController.java +++ b/src/main/java/co/orange/ddanzi/controller/AuthController.java @@ -1,18 +1,21 @@ package co.orange.ddanzi.controller; +import co.orange.ddanzi.common.error.Error; +import co.orange.ddanzi.common.response.Success; import co.orange.ddanzi.domain.user.enums.LoginType; import co.orange.ddanzi.dto.auth.RefreshTokenRequestDto; import co.orange.ddanzi.dto.auth.SigninRequestDto; import co.orange.ddanzi.dto.auth.VerifyRequestDto; import co.orange.ddanzi.common.response.ApiResponse; +import co.orange.ddanzi.global.jwt.JwtUtils; import co.orange.ddanzi.service.auth.AuthService; import co.orange.ddanzi.service.auth.OAuthService; import com.fasterxml.jackson.core.JsonProcessingException; +import jakarta.servlet.http.HttpServletRequest; import lombok.RequiredArgsConstructor; -import org.springframework.web.bind.annotation.PostMapping; -import org.springframework.web.bind.annotation.RequestBody; -import org.springframework.web.bind.annotation.RequestMapping; -import org.springframework.web.bind.annotation.RestController; +import org.springframework.web.bind.annotation.*; + +import java.util.Map; @RequiredArgsConstructor @RestController @@ -20,6 +23,7 @@ public class AuthController { private final AuthService authService; private final OAuthService oAuthService; + private final JwtUtils jwtUtils; @PostMapping("/signin/test") ApiResponse test(@RequestBody SigninRequestDto requestDto){ @@ -38,6 +42,19 @@ ApiResponse refreshAccessToken(@RequestBody RefreshTokenRequestDto requestDto return oAuthService.refreshAccessToken(requestDto.getRefreshtoken()); } + @PostMapping("/logout") + ApiResponse logout(HttpServletRequest request){ + String accesstoken = jwtUtils.resolveJWT(request); + if (accesstoken == null) { + return ApiResponse.onFailure(Error.JWT_TOKEN_NOT_EXISTS, null); + } + + // 블랙리스트에 토큰 추가 (로그아웃 처리) + jwtUtils.setBlackList(accesstoken); + + return ApiResponse.onSuccess(Success.LOGOUT_SUCCESS, true); + } + @PostMapping("/verification") ApiResponse verify(@RequestBody VerifyRequestDto requestDto) { return authService.verify(requestDto); diff --git a/src/main/java/co/orange/ddanzi/global/jwt/JwtUtils.java b/src/main/java/co/orange/ddanzi/global/jwt/JwtUtils.java index c45691cf..3b2caf49 100644 --- a/src/main/java/co/orange/ddanzi/global/jwt/JwtUtils.java +++ b/src/main/java/co/orange/ddanzi/global/jwt/JwtUtils.java @@ -161,9 +161,8 @@ public String getIdFromRefreshToken(String token) { .setSigningKey(jwtSecretKey) .parseClaimsJws(token) .getBody(); - return claims.get("email").toString(); // 이메일 정보 반환 + return claims.get("email").toString(); } catch (Exception e) { - // 토큰이 유효하지 않거나 에러 발생 시 null 반환 return null; } } @@ -173,10 +172,19 @@ public Claims getClaims(String token) { return Jwts.parser().setSigningKey(jwtSecretKey).parseClaimsJws(token).getBody(); } + public boolean isLogout(String accessToken) { return !ObjectUtils.isEmpty(stringRedisTemplate.opsForValue().get(accessToken)); } + public void setBlackList(String accessToken) { + Long expiration = getExpiration(accessToken); + stringRedisTemplate.opsForValue().set(accessToken, "logout", expiration, TimeUnit.MILLISECONDS); + } + public Long getExpiration(String token) { + Date expiration = getClaims(token).getExpiration(); + return expiration.getTime() - new Date().getTime(); + } } From 09a2daf3e6ba17a830dae5a025338f8a8e49785f Mon Sep 17 00:00:00 2001 From: kang Date: Tue, 20 Aug 2024 06:39:34 +0900 Subject: [PATCH 12/12] chore: change http status --- src/main/java/co/orange/ddanzi/common/response/Success.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/main/java/co/orange/ddanzi/common/response/Success.java b/src/main/java/co/orange/ddanzi/common/response/Success.java index 0403f90c..b0c21412 100644 --- a/src/main/java/co/orange/ddanzi/common/response/Success.java +++ b/src/main/java/co/orange/ddanzi/common/response/Success.java @@ -46,7 +46,6 @@ public enum Success { DELETE_INTEREST_SUCCESS(HttpStatus.OK, "Successfully removed the product from interest List."), DELETE_ADDRESS_SUCCESS(HttpStatus.OK, "Successfully deleted the delivery address."), DELETE_ACCOUNT_SUCCESS(HttpStatus.OK, "Successfully deleted the account"), - LOGOUT_SUCCESS(HttpStatus.OK, "Successfully log out the user"), // 201 CREATED @@ -54,6 +53,7 @@ public enum Success { SIGNIN_APPLE_SUCCESS(HttpStatus.CREATED, "Successfully sign in using Kakao"), REFRESH_ACCESS_TOKEN_SUCCESS(HttpStatus.CREATED, "Successfully refreshed access token."), + LOGOUT_SUCCESS(HttpStatus.CREATED, "Successfully log out the user"), SET_REDIS_KEY_SUCCESS(HttpStatus.CREATED, "Successfully set the redis key"),