From aeccc183c8ca9a3f5727354abc196d9c2b74fc37 Mon Sep 17 00:00:00 2001 From: seongjunnoh Date: Sun, 8 Sep 2024 15:37:02 +0900 Subject: [PATCH 01/26] =?UTF-8?q?refactor=20:=20OauthTestController=20?= =?UTF-8?q?=EC=BD=94=EB=93=9C=20->=20TestController=20=EB=A1=9C=20?= =?UTF-8?q?=EC=9D=B4=EB=8F=99?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../controller/TestController.java | 20 +++++++++++ .../controller/TestOAuthController.java | 33 ------------------- 2 files changed, 20 insertions(+), 33 deletions(-) delete mode 100644 src/main/java/space/space_spring/controller/TestOAuthController.java diff --git a/src/main/java/space/space_spring/controller/TestController.java b/src/main/java/space/space_spring/controller/TestController.java index a2e2f6cd..a0005697 100644 --- a/src/main/java/space/space_spring/controller/TestController.java +++ b/src/main/java/space/space_spring/controller/TestController.java @@ -1,6 +1,7 @@ package space.space_spring.controller; import lombok.extern.slf4j.Slf4j; +import org.springframework.beans.factory.annotation.Value; import org.springframework.web.bind.annotation.GetMapping; import org.springframework.web.bind.annotation.PathVariable; import org.springframework.web.bind.annotation.RestController; @@ -53,5 +54,24 @@ public BaseResponse LoginPassAnnotaionTest( } + /** + * 카카오 로그인 요청 처리 + * 카카오 인증 서버의 인증 및 동의 요청 페이지로 redirect + */ + @Value("${oauth.kakao.client.id}") + private String clientId; + + @Value("${oauth.kakao.redirect.uri}") + private String redirectUri; + + @GetMapping("/oauth/kakao") + public String kakaoConnect() { + StringBuffer url = new StringBuffer(); + url.append("https://kauth.kakao.com/oauth/authorize?"); + url.append("client_id="+clientId); + url.append("&redirect_uri="+redirectUri); + url.append("&response_type=code"); + return "redirect:" + url.toString(); + } } diff --git a/src/main/java/space/space_spring/controller/TestOAuthController.java b/src/main/java/space/space_spring/controller/TestOAuthController.java deleted file mode 100644 index 3006d483..00000000 --- a/src/main/java/space/space_spring/controller/TestOAuthController.java +++ /dev/null @@ -1,33 +0,0 @@ -package space.space_spring.controller; - -import lombok.extern.slf4j.Slf4j; -import org.springframework.beans.factory.annotation.Value; -import org.springframework.stereotype.Controller; -import org.springframework.web.bind.annotation.GetMapping; -import org.springframework.web.bind.annotation.RequestMapping; - -@Controller -@RequestMapping("/oauth") -@Slf4j -public class TestOAuthController { - - @Value("${oauth.kakao.client.id}") - private String clientId; - - @Value("${oauth.kakao.redirect.uri}") - private String redirectUri; - - /** - * 카카오 로그인 요청 처리 - * 카카오 인증 서버의 인증 및 동의 요청 페이지로 redirect - */ - @GetMapping("/kakao") - public String kakaoConnect() { - StringBuffer url = new StringBuffer(); - url.append("https://kauth.kakao.com/oauth/authorize?"); - url.append("client_id="+clientId); - url.append("&redirect_uri="+redirectUri); - url.append("&response_type=code"); - return "redirect:" + url.toString(); - } -} From 9f7c8e74fef2170dfa2a55eeea4744b8942fc90d Mon Sep 17 00:00:00 2001 From: seongjunnoh Date: Sun, 8 Sep 2024 16:29:48 +0900 Subject: [PATCH 02/26] =?UTF-8?q?feat=20:=20tokenDTO,=20enum=20=ED=81=B4?= =?UTF-8?q?=EB=9E=98=EC=8A=A4=20=EC=B6=94=EA=B0=80?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../space_spring/dto/jwt/JwtPayloadDto.java | 30 ------------------- .../dto/jwt/JwtUserSpaceAuthDto.java | 18 ----------- .../space/space_spring/dto/jwt/tokenDTO.java | 15 ++++++++++ .../space/space_spring/dto/jwt/tokenType.java | 6 ++++ 4 files changed, 21 insertions(+), 48 deletions(-) delete mode 100644 src/main/java/space/space_spring/dto/jwt/JwtPayloadDto.java delete mode 100644 src/main/java/space/space_spring/dto/jwt/JwtUserSpaceAuthDto.java create mode 100644 src/main/java/space/space_spring/dto/jwt/tokenDTO.java create mode 100644 src/main/java/space/space_spring/dto/jwt/tokenType.java diff --git a/src/main/java/space/space_spring/dto/jwt/JwtPayloadDto.java b/src/main/java/space/space_spring/dto/jwt/JwtPayloadDto.java deleted file mode 100644 index f697f852..00000000 --- a/src/main/java/space/space_spring/dto/jwt/JwtPayloadDto.java +++ /dev/null @@ -1,30 +0,0 @@ -package space.space_spring.dto.jwt; - -import lombok.Getter; -import lombok.NoArgsConstructor; -import lombok.ToString; - -import java.util.ArrayList; -import java.util.List; - -@Getter -@NoArgsConstructor -@ToString -public class JwtPayloadDto { - - private Long userId; - - private List userSpaceList = new ArrayList<>(); - - public void saveUserIdToJwt(Long userId) { - this.userId = userId; - } - - public void saveUserSpaceList(List userSpaceList) { - this.userSpaceList = userSpaceList; - } - - public void addJwtUserSpaceAuth(JwtUserSpaceAuthDto jwtUserSpaceAuthDto) { - this.userSpaceList.add(jwtUserSpaceAuthDto); - } -} diff --git a/src/main/java/space/space_spring/dto/jwt/JwtUserSpaceAuthDto.java b/src/main/java/space/space_spring/dto/jwt/JwtUserSpaceAuthDto.java deleted file mode 100644 index ab6c4f56..00000000 --- a/src/main/java/space/space_spring/dto/jwt/JwtUserSpaceAuthDto.java +++ /dev/null @@ -1,18 +0,0 @@ -package space.space_spring.dto.jwt; - -import lombok.Getter; -import lombok.ToString; - -import java.util.HashMap; -import java.util.Map; - -@Getter -@ToString -public class JwtUserSpaceAuthDto { - - private Map userSpaceAuthMap = new HashMap<>(); - - public void saveUserSpaceAuth(Long spaceId, String userSpaceAuth) { - userSpaceAuthMap.put(spaceId, userSpaceAuth); - } -} diff --git a/src/main/java/space/space_spring/dto/jwt/tokenDTO.java b/src/main/java/space/space_spring/dto/jwt/tokenDTO.java new file mode 100644 index 00000000..e0d1fe1f --- /dev/null +++ b/src/main/java/space/space_spring/dto/jwt/tokenDTO.java @@ -0,0 +1,15 @@ +package space.space_spring.dto.jwt; + +import lombok.AllArgsConstructor; +import lombok.Builder; +import lombok.Getter; +import lombok.NoArgsConstructor; + +@Getter +@NoArgsConstructor +@AllArgsConstructor +public class tokenDTO { + + private String refreshToken; + private String accessToken; +} diff --git a/src/main/java/space/space_spring/dto/jwt/tokenType.java b/src/main/java/space/space_spring/dto/jwt/tokenType.java new file mode 100644 index 00000000..31ad7866 --- /dev/null +++ b/src/main/java/space/space_spring/dto/jwt/tokenType.java @@ -0,0 +1,6 @@ +package space.space_spring.dto.jwt; + +public enum tokenType { + REFRESH, + ACCESS +} From 7e6e479f715326377556b145e52c0a1fb0276f82 Mon Sep 17 00:00:00 2001 From: seongjunnoh Date: Sun, 8 Sep 2024 16:42:04 +0900 Subject: [PATCH 03/26] =?UTF-8?q?refactor=20:=20login=20=EB=A9=94=EC=84=9C?= =?UTF-8?q?=EB=93=9C=EC=97=90=EC=84=9C=20jwt=20=ED=83=80=EC=9E=85=EB=B3=84?= =?UTF-8?q?=EB=A1=9C=20=ED=86=A0=ED=81=B0=20=EB=B0=9C=EA=B8=89=20=EC=9A=94?= =?UTF-8?q?=EC=B2=AD=ED=95=98=EB=8F=84=EB=A1=9D=20=EC=88=98=EC=A0=95?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../space_spring/controller/UserController.java | 5 +---- .../dto/jwt/{tokenDTO.java => TokenDTO.java} | 3 +-- .../dto/jwt/{tokenType.java => TokenType.java} | 2 +- .../space/space_spring/dto/user/PostLoginDto.java | 6 ++---- .../space/space_spring/jwt/JwtLoginProvider.java | 3 ++- .../space/space_spring/service/UserService.java | 14 ++++++++------ 6 files changed, 15 insertions(+), 18 deletions(-) rename src/main/java/space/space_spring/dto/jwt/{tokenDTO.java => TokenDTO.java} (83%) rename src/main/java/space/space_spring/dto/jwt/{tokenType.java => TokenType.java} (72%) diff --git a/src/main/java/space/space_spring/controller/UserController.java b/src/main/java/space/space_spring/controller/UserController.java index dd2d405e..7e29b482 100644 --- a/src/main/java/space/space_spring/controller/UserController.java +++ b/src/main/java/space/space_spring/controller/UserController.java @@ -55,10 +55,7 @@ public BaseResponse login(@Validated @RequestBody PostLog throw new CustomException(INVALID_USER_LOGIN, getErrorMessage(bindingResult)); } - PostLoginDto login = userService.login(request); - response.setHeader("Authorization", "Bearer " + login.getJwt()); - - return new BaseResponse<>(new PostLoginDto.Response(login.getUserId())); + return new BaseResponse<>(userService.login(request)); } /** diff --git a/src/main/java/space/space_spring/dto/jwt/tokenDTO.java b/src/main/java/space/space_spring/dto/jwt/TokenDTO.java similarity index 83% rename from src/main/java/space/space_spring/dto/jwt/tokenDTO.java rename to src/main/java/space/space_spring/dto/jwt/TokenDTO.java index e0d1fe1f..8cb7d1f0 100644 --- a/src/main/java/space/space_spring/dto/jwt/tokenDTO.java +++ b/src/main/java/space/space_spring/dto/jwt/TokenDTO.java @@ -1,14 +1,13 @@ package space.space_spring.dto.jwt; import lombok.AllArgsConstructor; -import lombok.Builder; import lombok.Getter; import lombok.NoArgsConstructor; @Getter @NoArgsConstructor @AllArgsConstructor -public class tokenDTO { +public class TokenDTO { private String refreshToken; private String accessToken; diff --git a/src/main/java/space/space_spring/dto/jwt/tokenType.java b/src/main/java/space/space_spring/dto/jwt/TokenType.java similarity index 72% rename from src/main/java/space/space_spring/dto/jwt/tokenType.java rename to src/main/java/space/space_spring/dto/jwt/TokenType.java index 31ad7866..ec125cfe 100644 --- a/src/main/java/space/space_spring/dto/jwt/tokenType.java +++ b/src/main/java/space/space_spring/dto/jwt/TokenType.java @@ -1,6 +1,6 @@ package space.space_spring.dto.jwt; -public enum tokenType { +public enum TokenType { REFRESH, ACCESS } diff --git a/src/main/java/space/space_spring/dto/user/PostLoginDto.java b/src/main/java/space/space_spring/dto/user/PostLoginDto.java index ca2f6068..2eb6b7b8 100644 --- a/src/main/java/space/space_spring/dto/user/PostLoginDto.java +++ b/src/main/java/space/space_spring/dto/user/PostLoginDto.java @@ -6,16 +6,13 @@ import lombok.Getter; import lombok.NoArgsConstructor; import lombok.Setter; +import space.space_spring.dto.jwt.TokenDTO; @Getter @NoArgsConstructor @AllArgsConstructor public class PostLoginDto { - private String jwt; - - private Long userId; - @Getter @Setter @NoArgsConstructor @@ -37,6 +34,7 @@ public static class Request { @AllArgsConstructor public static class Response { + private TokenDTO tokenDTO; private Long userId; } } diff --git a/src/main/java/space/space_spring/jwt/JwtLoginProvider.java b/src/main/java/space/space_spring/jwt/JwtLoginProvider.java index 7427b8c4..a8ccc7c5 100644 --- a/src/main/java/space/space_spring/jwt/JwtLoginProvider.java +++ b/src/main/java/space/space_spring/jwt/JwtLoginProvider.java @@ -4,6 +4,7 @@ import lombok.extern.slf4j.Slf4j; import org.springframework.beans.factory.annotation.Value; import org.springframework.stereotype.Component; +import space.space_spring.dto.jwt.TokenType; import space.space_spring.entity.User; import space.space_spring.exception.CustomException; import space.space_spring.exception.jwt.bad_request.JwtUnsupportedTokenException; @@ -24,7 +25,7 @@ public class JwtLoginProvider { private Long JWT_EXPIRED_IN; - public String generateToken(User user) { + public String generateToken(User user, TokenType tokenType) { // Claims claims = Jwts.claims().setSubject(jwtPayloadDto.getUserId().toString()); Date now = new Date(); diff --git a/src/main/java/space/space_spring/service/UserService.java b/src/main/java/space/space_spring/service/UserService.java index 95439c75..9480b46a 100644 --- a/src/main/java/space/space_spring/service/UserService.java +++ b/src/main/java/space/space_spring/service/UserService.java @@ -5,6 +5,8 @@ import org.springframework.stereotype.Service; import org.springframework.transaction.annotation.Transactional; import space.space_spring.dao.UserSpaceDao; +import space.space_spring.dto.jwt.TokenDTO; +import space.space_spring.dto.jwt.TokenType; import space.space_spring.dto.user.GetUserProfileListDto; import space.space_spring.dto.user.PostLoginDto; import space.space_spring.dto.user.dto.SpaceChoiceViewDto; @@ -60,7 +62,7 @@ private void validateEmailForLocalSignup(String email) { } @Transactional - public PostLoginDto login(PostLoginDto.Request request) { + public PostLoginDto.Response login(PostLoginDto.Request request) { // TODO 1. 이메일 존재 여부 확인(아이디 존재 여부 확인) User userByEmail = userUtils.findUserByEmail(request.getEmail(), LOCAL); log.info("userByEmail.getUserId: {}", userByEmail.getUserId()); @@ -68,12 +70,12 @@ public PostLoginDto login(PostLoginDto.Request request) { // TODO 2. 비밀번호 일치 여부 확인 validatePassword(userByEmail, request.getPassword()); - // TODO 3. JWT 발급 - String jwtLogin = jwtLoginProvider.generateToken(userByEmail); - log.info("jwtLogin: {}", jwtLogin); + // TODO 3. JWT 발급 -> access token, refresh token 2개 발급 + String accessToken = jwtLoginProvider.generateToken(userByEmail, TokenType.ACCESS); + String refreshToken = jwtLoginProvider.generateToken(userByEmail, TokenType.REFRESH); - return new PostLoginDto( - jwtLogin, + return new PostLoginDto.Response( + new TokenDTO(accessToken, refreshToken), userByEmail.getUserId() ); } From c6dec8c0b7941c2e405b8003e5e6b4401a240ff7 Mon Sep 17 00:00:00 2001 From: seongjunnoh Date: Sun, 8 Sep 2024 17:04:57 +0900 Subject: [PATCH 04/26] =?UTF-8?q?refactor=20:=20generateToken=20=EB=A9=94?= =?UTF-8?q?=EC=84=9C=EB=93=9C=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 --- .../space/space_spring/jwt/JwtLoginProvider.java | 13 ++++++++++++- 1 file changed, 12 insertions(+), 1 deletion(-) diff --git a/src/main/java/space/space_spring/jwt/JwtLoginProvider.java b/src/main/java/space/space_spring/jwt/JwtLoginProvider.java index a8ccc7c5..6d4ad5b7 100644 --- a/src/main/java/space/space_spring/jwt/JwtLoginProvider.java +++ b/src/main/java/space/space_spring/jwt/JwtLoginProvider.java @@ -24,12 +24,13 @@ public class JwtLoginProvider { @Value("${secret.jwt-expired-in}") private Long JWT_EXPIRED_IN; + private static int times = 168; // 1시간 * times == refresh token 만료 시간 public String generateToken(User user, TokenType tokenType) { // Claims claims = Jwts.claims().setSubject(jwtPayloadDto.getUserId().toString()); Date now = new Date(); - Date expiration = new Date(now.getTime() + JWT_EXPIRED_IN); + Date expiration = setExpiration(now, tokenType); Long userId = user.getUserId(); @@ -42,6 +43,16 @@ public String generateToken(User user, TokenType tokenType) { .compact(); } + private Date setExpiration(Date now, TokenType tokenType) { + if (tokenType.equals(TokenType.ACCESS)) { + // 엑세스 토큰 : 1시간 + return new Date(now.getTime() + JWT_EXPIRED_IN); + } + + // 리프레쉬 토큰 : 7일 + return new Date(now.getTime() + JWT_EXPIRED_IN * times); + } + public boolean isExpiredToken(String accessToken) { try { Jws claims = Jwts.parserBuilder() From 380206699a16c99187ebcccc3ed03593317326c2 Mon Sep 17 00:00:00 2001 From: seongjunnoh Date: Sun, 8 Sep 2024 17:28:57 +0900 Subject: [PATCH 05/26] =?UTF-8?q?feat=20:=20=EB=A1=9C=EC=BB=AC=20=EB=A1=9C?= =?UTF-8?q?=EA=B7=B8=EC=9D=B8=20=EC=8B=9C=20refresh,=20access=20token=20?= =?UTF-8?q?=EB=B0=9C=EA=B8=89=20&=20response=20=ED=97=A4=EB=8D=94=EC=97=90?= =?UTF-8?q?=20=EC=B6=94=EA=B0=80?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../space/space_spring/controller/UserController.java | 7 ++++++- .../space/space_spring/dto/user/PostLoginDto.java | 4 +++- src/main/java/space/space_spring/entity/User.java | 11 +++++++++++ .../java/space/space_spring/service/OAuthService.java | 3 ++- .../java/space/space_spring/service/UserService.java | 7 +++++-- 5 files changed, 27 insertions(+), 5 deletions(-) diff --git a/src/main/java/space/space_spring/controller/UserController.java b/src/main/java/space/space_spring/controller/UserController.java index 7e29b482..f276c92e 100644 --- a/src/main/java/space/space_spring/controller/UserController.java +++ b/src/main/java/space/space_spring/controller/UserController.java @@ -55,7 +55,12 @@ public BaseResponse login(@Validated @RequestBody PostLog throw new CustomException(INVALID_USER_LOGIN, getErrorMessage(bindingResult)); } - return new BaseResponse<>(userService.login(request)); + PostLoginDto login = userService.login(request); + + response.setHeader("Authorization-refresh", "Bearer " + login.getTokenDTO().getRefreshToken()); + response.setHeader("Authorization", "Bearer " + login.getTokenDTO().getAccessToken()); + + return new BaseResponse<>(new PostLoginDto.Response(login.getUserId())); } /** diff --git a/src/main/java/space/space_spring/dto/user/PostLoginDto.java b/src/main/java/space/space_spring/dto/user/PostLoginDto.java index 2eb6b7b8..5202d58f 100644 --- a/src/main/java/space/space_spring/dto/user/PostLoginDto.java +++ b/src/main/java/space/space_spring/dto/user/PostLoginDto.java @@ -13,6 +13,9 @@ @AllArgsConstructor public class PostLoginDto { + private TokenDTO tokenDTO; + private Long userId; + @Getter @Setter @NoArgsConstructor @@ -34,7 +37,6 @@ public static class Request { @AllArgsConstructor public static class Response { - private TokenDTO tokenDTO; private Long userId; } } diff --git a/src/main/java/space/space_spring/entity/User.java b/src/main/java/space/space_spring/entity/User.java index 120ed335..255f7d0b 100644 --- a/src/main/java/space/space_spring/entity/User.java +++ b/src/main/java/space/space_spring/entity/User.java @@ -26,6 +26,17 @@ public class User extends BaseEntity { @Column(name = "signup_type") private String signupType; // 유저가 회원가입을 진행한 방식 (local, kakao, naver, google 등등) + @Column(name = "refresh_token") + private String refreshToken; + + public void updateRefreshToken(String refreshToken) { + this.refreshToken = refreshToken; + } + + public void destroyRefreshToken() { + this.refreshToken = null; + } + public void saveUser(String email, String password, String userName, UserSignupType signupType) { this.email = email; this.password = password; diff --git a/src/main/java/space/space_spring/service/OAuthService.java b/src/main/java/space/space_spring/service/OAuthService.java index 9d8902f7..9302b7be 100644 --- a/src/main/java/space/space_spring/service/OAuthService.java +++ b/src/main/java/space/space_spring/service/OAuthService.java @@ -13,6 +13,7 @@ import org.springframework.util.LinkedMultiValueMap; import org.springframework.util.MultiValueMap; import org.springframework.web.client.RestTemplate; +import space.space_spring.dto.jwt.TokenType; import space.space_spring.dto.oAuth.KakaoInfo; import space.space_spring.entity.User; import space.space_spring.jwt.JwtLoginProvider; @@ -104,6 +105,6 @@ public User findUserByOAuthInfo(KakaoInfo kakaoInfo) { } public String provideJwtToOAuthUser(User userByOAuthInfo) { - return jwtLoginProvider.generateToken(userByOAuthInfo); + return jwtLoginProvider.generateToken(userByOAuthInfo, TokenType.ACCESS); } } diff --git a/src/main/java/space/space_spring/service/UserService.java b/src/main/java/space/space_spring/service/UserService.java index 9480b46a..8ce63489 100644 --- a/src/main/java/space/space_spring/service/UserService.java +++ b/src/main/java/space/space_spring/service/UserService.java @@ -62,7 +62,7 @@ private void validateEmailForLocalSignup(String email) { } @Transactional - public PostLoginDto.Response login(PostLoginDto.Request request) { + public PostLoginDto login(PostLoginDto.Request request) { // TODO 1. 이메일 존재 여부 확인(아이디 존재 여부 확인) User userByEmail = userUtils.findUserByEmail(request.getEmail(), LOCAL); log.info("userByEmail.getUserId: {}", userByEmail.getUserId()); @@ -74,7 +74,10 @@ public PostLoginDto.Response login(PostLoginDto.Request request) { String accessToken = jwtLoginProvider.generateToken(userByEmail, TokenType.ACCESS); String refreshToken = jwtLoginProvider.generateToken(userByEmail, TokenType.REFRESH); - return new PostLoginDto.Response( + // TODO 4. refresh token db에 저장 + userByEmail.updateRefreshToken(refreshToken); + + return new PostLoginDto ( new TokenDTO(accessToken, refreshToken), userByEmail.getUserId() ); From d7bdf99b65da3984ae4ab3da41f4b14704b5b11e Mon Sep 17 00:00:00 2001 From: seongjunnoh Date: Sun, 8 Sep 2024 20:55:43 +0900 Subject: [PATCH 06/26] =?UTF-8?q?feat=20:=20=EC=B9=B4=EC=B9=B4=EC=98=A4=20?= =?UTF-8?q?=EB=A1=9C=EA=B7=B8=EC=9D=B8=20=EC=8B=9C=20refresh=20token=20?= =?UTF-8?q?=EB=B0=9C=EA=B8=89=20=EC=B6=94=EA=B0=80?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../controller/OAuthController.java | 19 +++++++---- .../controller/TestController.java | 21 ------------ .../controller/ViewTestController.java | 33 +++++++++++++++++++ .../space_spring/service/OAuthService.java | 8 +++-- 4 files changed, 51 insertions(+), 30 deletions(-) create mode 100644 src/main/java/space/space_spring/controller/ViewTestController.java diff --git a/src/main/java/space/space_spring/controller/OAuthController.java b/src/main/java/space/space_spring/controller/OAuthController.java index 631e0414..4665530a 100644 --- a/src/main/java/space/space_spring/controller/OAuthController.java +++ b/src/main/java/space/space_spring/controller/OAuthController.java @@ -9,6 +9,7 @@ import org.springframework.web.bind.annotation.RequestMapping; import org.springframework.web.bind.annotation.RequestParam; import org.springframework.web.bind.annotation.RestController; +import space.space_spring.dto.jwt.TokenDTO; import space.space_spring.dto.oAuth.KakaoInfo; import space.space_spring.dto.oAuth.OAuthLoginResponse; import space.space_spring.entity.User; @@ -69,18 +70,22 @@ public void kakaoCallback(@RequestParam(name = "code") String code, HttpServletR User userByOAuthInfo = oAuthService.findUserByOAuthInfo(kakaoInfo); // TODO 5. 카카오 로그인 유저에게 jwt 발급 - String jwtOAuthLogin = oAuthService.provideJwtToOAuthUser(userByOAuthInfo); - response.setHeader("Authorization", "Bearer " + jwtOAuthLogin); - log.info("jwtOAuthLogin = {}", jwtOAuthLogin); + TokenDTO tokenDTO = oAuthService.provideJwtToOAuthUser(userByOAuthInfo); + userByOAuthInfo.updateRefreshToken(tokenDTO.getRefreshToken()); - // Construct the redirect URL with the JWT and userId as query parameters + System.out.println("tokenDTO.getAccessToken() = " + tokenDTO.getAccessToken()); + System.out.println("tokenDTO.getRefreshToken() = " + tokenDTO.getRefreshToken()); + + // 클라이언트로 response 전달 + // -> 메서드 분리 ?? + // 공백문자가 %20 으로 전달되는 듯 함 -> 프론트 분들과 협의 필요할 듯 String redirectUrl = String.format( - "https://kuit-space.github.io/KUIT-Space-front/login?jwt=Bearer %s&userId=%s", - jwtOAuthLogin, + "https://kuit-space.github.io/KUIT-Space-front/login?access-token=%s&refresh-token=%s&userId=%s", + "Bearer " + tokenDTO.getAccessToken(), + "Bearer " + tokenDTO.getRefreshToken(), userByOAuthInfo.getUserId() ); - // Redirect to the specified URL response.sendRedirect(redirectUrl); } } diff --git a/src/main/java/space/space_spring/controller/TestController.java b/src/main/java/space/space_spring/controller/TestController.java index a0005697..25f09cb0 100644 --- a/src/main/java/space/space_spring/controller/TestController.java +++ b/src/main/java/space/space_spring/controller/TestController.java @@ -53,25 +53,4 @@ public BaseResponse LoginPassAnnotaionTest( +""); } - - /** - * 카카오 로그인 요청 처리 - * 카카오 인증 서버의 인증 및 동의 요청 페이지로 redirect - */ - @Value("${oauth.kakao.client.id}") - private String clientId; - - @Value("${oauth.kakao.redirect.uri}") - private String redirectUri; - - @GetMapping("/oauth/kakao") - public String kakaoConnect() { - StringBuffer url = new StringBuffer(); - url.append("https://kauth.kakao.com/oauth/authorize?"); - url.append("client_id="+clientId); - url.append("&redirect_uri="+redirectUri); - url.append("&response_type=code"); - return "redirect:" + url.toString(); - } - } diff --git a/src/main/java/space/space_spring/controller/ViewTestController.java b/src/main/java/space/space_spring/controller/ViewTestController.java new file mode 100644 index 00000000..327a225f --- /dev/null +++ b/src/main/java/space/space_spring/controller/ViewTestController.java @@ -0,0 +1,33 @@ +package space.space_spring.controller; + +import lombok.Getter; +import lombok.RequiredArgsConstructor; +import lombok.extern.slf4j.Slf4j; +import org.springframework.beans.factory.annotation.Value; +import org.springframework.stereotype.Controller; +import org.springframework.web.bind.annotation.GetMapping; + +@Controller +@Slf4j +public class ViewTestController { + + /** + * 카카오 로그인 요청 처리 + * 카카오 인증 서버의 인증 및 동의 요청 페이지로 redirect + */ + @Value("${oauth.kakao.client.id}") + private String clientId; + + @Value("${oauth.kakao.redirect.uri}") + private String redirectUri; + + @GetMapping("/oauth/kakao") + public String kakaoConnect() { + StringBuffer url = new StringBuffer(); + url.append("https://kauth.kakao.com/oauth/authorize?"); + url.append("client_id="+clientId); + url.append("&redirect_uri="+redirectUri); + url.append("&response_type=code"); + return "redirect:" + url.toString(); + } +} diff --git a/src/main/java/space/space_spring/service/OAuthService.java b/src/main/java/space/space_spring/service/OAuthService.java index 9302b7be..9d5d953a 100644 --- a/src/main/java/space/space_spring/service/OAuthService.java +++ b/src/main/java/space/space_spring/service/OAuthService.java @@ -13,6 +13,7 @@ import org.springframework.util.LinkedMultiValueMap; import org.springframework.util.MultiValueMap; import org.springframework.web.client.RestTemplate; +import space.space_spring.dto.jwt.TokenDTO; import space.space_spring.dto.jwt.TokenType; import space.space_spring.dto.oAuth.KakaoInfo; import space.space_spring.entity.User; @@ -104,7 +105,10 @@ public User findUserByOAuthInfo(KakaoInfo kakaoInfo) { return userUtils.findOrCreateUserForOAuthInfo(email, nickname, KAKAO); } - public String provideJwtToOAuthUser(User userByOAuthInfo) { - return jwtLoginProvider.generateToken(userByOAuthInfo, TokenType.ACCESS); + public TokenDTO provideJwtToOAuthUser(User userByOAuthInfo) { + String accessToken = jwtLoginProvider.generateToken(userByOAuthInfo, TokenType.ACCESS); + String refreshToken = jwtLoginProvider.generateToken(userByOAuthInfo, TokenType.REFRESH); + + return new TokenDTO(accessToken, refreshToken); } } From 2f56cfdcd492e64c8495e4758d5e07cdd11e4afb Mon Sep 17 00:00:00 2001 From: seongjunnoh Date: Sun, 8 Sep 2024 21:15:43 +0900 Subject: [PATCH 07/26] =?UTF-8?q?feat=20:=20=EC=B9=B4=EC=B9=B4=EC=98=A4=20?= =?UTF-8?q?=EB=A1=9C=EA=B7=B8=EC=9D=B8=20=EC=8B=9C=20refresh=20token=20?= =?UTF-8?q?=EC=A0=95=EB=B3=B4=20db=EC=97=90=20=EC=A0=80=EC=9E=A5?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../java/space/space_spring/controller/OAuthController.java | 1 - .../space/space_spring/controller/ViewTestController.java | 1 + src/main/java/space/space_spring/service/OAuthService.java | 6 ++++++ 3 files changed, 7 insertions(+), 1 deletion(-) diff --git a/src/main/java/space/space_spring/controller/OAuthController.java b/src/main/java/space/space_spring/controller/OAuthController.java index 4665530a..93ffb405 100644 --- a/src/main/java/space/space_spring/controller/OAuthController.java +++ b/src/main/java/space/space_spring/controller/OAuthController.java @@ -71,7 +71,6 @@ public void kakaoCallback(@RequestParam(name = "code") String code, HttpServletR // TODO 5. 카카오 로그인 유저에게 jwt 발급 TokenDTO tokenDTO = oAuthService.provideJwtToOAuthUser(userByOAuthInfo); - userByOAuthInfo.updateRefreshToken(tokenDTO.getRefreshToken()); System.out.println("tokenDTO.getAccessToken() = " + tokenDTO.getAccessToken()); System.out.println("tokenDTO.getRefreshToken() = " + tokenDTO.getRefreshToken()); diff --git a/src/main/java/space/space_spring/controller/ViewTestController.java b/src/main/java/space/space_spring/controller/ViewTestController.java index 327a225f..bb5c7509 100644 --- a/src/main/java/space/space_spring/controller/ViewTestController.java +++ b/src/main/java/space/space_spring/controller/ViewTestController.java @@ -10,6 +10,7 @@ @Controller @Slf4j public class ViewTestController { + // RestController가 아니라 Controller 의 테스트가 필요할 경우 /** * 카카오 로그인 요청 처리 diff --git a/src/main/java/space/space_spring/service/OAuthService.java b/src/main/java/space/space_spring/service/OAuthService.java index 9d5d953a..cc4835cc 100644 --- a/src/main/java/space/space_spring/service/OAuthService.java +++ b/src/main/java/space/space_spring/service/OAuthService.java @@ -105,10 +105,16 @@ public User findUserByOAuthInfo(KakaoInfo kakaoInfo) { return userUtils.findOrCreateUserForOAuthInfo(email, nickname, KAKAO); } + @Transactional public TokenDTO provideJwtToOAuthUser(User userByOAuthInfo) { + + // TODO 1. access token, refresh token 발급 String accessToken = jwtLoginProvider.generateToken(userByOAuthInfo, TokenType.ACCESS); String refreshToken = jwtLoginProvider.generateToken(userByOAuthInfo, TokenType.REFRESH); + // TODO 2. 카카오 로그인을 이용한 유저의 refresh token 정보 db에 저장 + userByOAuthInfo.updateRefreshToken(refreshToken); + return new TokenDTO(accessToken, refreshToken); } } From b38cbd7f9afa884851499b15e6da621191e41afb Mon Sep 17 00:00:00 2001 From: seongjunnoh Date: Sun, 8 Sep 2024 23:58:54 +0900 Subject: [PATCH 08/26] =?UTF-8?q?feat=20:=20access=20token=20=EB=A7=8C?= =?UTF-8?q?=EB=A3=8C=EC=8B=9C=20refresh=20token=EC=9D=84=20=ED=8F=AC?= =?UTF-8?q?=ED=95=A8=ED=95=9C=20access=20token=20=EA=B0=B1=EC=8B=A0=20?= =?UTF-8?q?=EC=9A=94=EC=B2=AD=EC=97=90=20=EB=8C=80=ED=95=9C=20interceptor?= =?UTF-8?q?=20=EC=B6=94=EA=B0=80?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../space/space_spring/config/WebConfig.java | 17 ++++-- .../RefreshTokenInterceptorURL.java | 15 ++++++ .../controller/OAuthController.java | 7 +-- .../controller/UserController.java | 1 + .../jwtLogin/JwtLoginAuthInterceptor.java | 1 - .../refreshToken/RefreshTokenInterceptor.java | 52 +++++++++++++++++++ 6 files changed, 83 insertions(+), 10 deletions(-) create mode 100644 src/main/java/space/space_spring/config/interceptorURL/RefreshTokenInterceptorURL.java create mode 100644 src/main/java/space/space_spring/interceptor/refreshToken/RefreshTokenInterceptor.java diff --git a/src/main/java/space/space_spring/config/WebConfig.java b/src/main/java/space/space_spring/config/WebConfig.java index 3a0fca90..1319ed6d 100644 --- a/src/main/java/space/space_spring/config/WebConfig.java +++ b/src/main/java/space/space_spring/config/WebConfig.java @@ -11,7 +11,9 @@ import space.space_spring.argumentResolver.userSpace.UserSpaceAuthHandlerArgumentResolver; import space.space_spring.argumentResolver.userSpace.UserSpaceIdHandlerArgumentResolver; import space.space_spring.config.interceptorURL.JwtLoginInterceptorURL; +import space.space_spring.config.interceptorURL.RefreshTokenInterceptorURL; import space.space_spring.config.interceptorURL.UserSpaceValidationInterceptorURL; +import space.space_spring.interceptor.refreshToken.RefreshTokenInterceptor; import space.space_spring.interceptor.UserSpaceValidationInterceptor; import space.space_spring.interceptor.jwtLogin.JwtLoginAuthInterceptor; @@ -22,11 +24,12 @@ public class WebConfig implements WebMvcConfigurer { private final JwtLoginAuthInterceptor jwtLoginAuthInterceptor; + private final UserSpaceValidationInterceptor userSpaceValidationInterceptor; + private final RefreshTokenInterceptor refreshTokenInterceptor; private final JwtLoginAuthHandlerArgumentResolver jwtLoginAuthHandlerArgumentResolver; private final UserSpaceIdHandlerArgumentResolver userSpaceIdHandlerArgumentResolver; private final UserSpaceAuthHandlerArgumentResolver userSpaceAuthHandlerArgumentResolver; - private final UserSpaceValidationInterceptor userSpaceValidationInterceptor; @Override @@ -39,14 +42,20 @@ public void addInterceptors(InterceptorRegistry registry) { registration.addPathPatterns(interceptorURL.getUrlPattern()); } + InterceptorRegistration refreshTokenRegistration = + registry.addInterceptor(refreshTokenInterceptor) + .order(2); + + for (RefreshTokenInterceptorURL interceptorURL : RefreshTokenInterceptorURL.values()) { + registration.addPathPatterns(interceptorURL.getUrlPattern()); + } + InterceptorRegistration userSpaceRegistration = registry.addInterceptor(userSpaceValidationInterceptor) - .order(2); + .order(3); for(UserSpaceValidationInterceptorURL url:UserSpaceValidationInterceptorURL.values()) { userSpaceRegistration.addPathPatterns(url.getUrlPattern()); } - - } @Override diff --git a/src/main/java/space/space_spring/config/interceptorURL/RefreshTokenInterceptorURL.java b/src/main/java/space/space_spring/config/interceptorURL/RefreshTokenInterceptorURL.java new file mode 100644 index 00000000..f3a3011a --- /dev/null +++ b/src/main/java/space/space_spring/config/interceptorURL/RefreshTokenInterceptorURL.java @@ -0,0 +1,15 @@ +package space.space_spring.config.interceptorURL; + +import lombok.Getter; + +@Getter +public enum RefreshTokenInterceptorURL { + + ASK_NEW_ACCESS_TOKEN("/oauth/new-access-token"); + + private final String urlPattern; + + RefreshTokenInterceptorURL(String urlPattern) { + this.urlPattern = urlPattern; + } +} diff --git a/src/main/java/space/space_spring/controller/OAuthController.java b/src/main/java/space/space_spring/controller/OAuthController.java index 93ffb405..68011122 100644 --- a/src/main/java/space/space_spring/controller/OAuthController.java +++ b/src/main/java/space/space_spring/controller/OAuthController.java @@ -5,10 +5,7 @@ import lombok.RequiredArgsConstructor; import lombok.extern.slf4j.Slf4j; import org.springframework.beans.factory.annotation.Value; -import org.springframework.web.bind.annotation.GetMapping; -import org.springframework.web.bind.annotation.RequestMapping; -import org.springframework.web.bind.annotation.RequestParam; -import org.springframework.web.bind.annotation.RestController; +import org.springframework.web.bind.annotation.*; import space.space_spring.dto.jwt.TokenDTO; import space.space_spring.dto.oAuth.KakaoInfo; import space.space_spring.dto.oAuth.OAuthLoginResponse; @@ -74,7 +71,7 @@ public void kakaoCallback(@RequestParam(name = "code") String code, HttpServletR System.out.println("tokenDTO.getAccessToken() = " + tokenDTO.getAccessToken()); System.out.println("tokenDTO.getRefreshToken() = " + tokenDTO.getRefreshToken()); - + // 클라이언트로 response 전달 // -> 메서드 분리 ?? // 공백문자가 %20 으로 전달되는 듯 함 -> 프론트 분들과 협의 필요할 듯 diff --git a/src/main/java/space/space_spring/controller/UserController.java b/src/main/java/space/space_spring/controller/UserController.java index f276c92e..ce827fc0 100644 --- a/src/main/java/space/space_spring/controller/UserController.java +++ b/src/main/java/space/space_spring/controller/UserController.java @@ -83,4 +83,5 @@ public BaseResponse showUserProfileList(@JwtLogi return new BaseResponse<>(userService.getUserProfileList(userId)); } + } diff --git a/src/main/java/space/space_spring/interceptor/jwtLogin/JwtLoginAuthInterceptor.java b/src/main/java/space/space_spring/interceptor/jwtLogin/JwtLoginAuthInterceptor.java index d196a683..e61fa3fe 100644 --- a/src/main/java/space/space_spring/interceptor/jwtLogin/JwtLoginAuthInterceptor.java +++ b/src/main/java/space/space_spring/interceptor/jwtLogin/JwtLoginAuthInterceptor.java @@ -37,7 +37,6 @@ private void validateAccessToken(String accessToken) { if (jwtLoginProvider.isExpiredToken(accessToken)) { throw new JwtExpiredTokenException(EXPIRED_TOKEN); } - } private String resolveAccessToken(HttpServletRequest request) { diff --git a/src/main/java/space/space_spring/interceptor/refreshToken/RefreshTokenInterceptor.java b/src/main/java/space/space_spring/interceptor/refreshToken/RefreshTokenInterceptor.java new file mode 100644 index 00000000..b266cf9b --- /dev/null +++ b/src/main/java/space/space_spring/interceptor/refreshToken/RefreshTokenInterceptor.java @@ -0,0 +1,52 @@ +package space.space_spring.interceptor.refreshToken; + +import jakarta.servlet.http.HttpServletRequest; +import jakarta.servlet.http.HttpServletResponse; +import lombok.RequiredArgsConstructor; +import org.springframework.http.HttpHeaders; +import org.springframework.stereotype.Component; +import org.springframework.web.servlet.HandlerInterceptor; +import space.space_spring.exception.jwt.bad_request.JwtNoTokenException; +import space.space_spring.exception.jwt.bad_request.JwtUnsupportedTokenException; +import space.space_spring.exception.jwt.unauthorized.JwtExpiredTokenException; +import space.space_spring.jwt.JwtLoginProvider; + +import static space.space_spring.response.status.BaseExceptionResponseStatus.*; + +@Component +@RequiredArgsConstructor +public class RefreshTokenInterceptor implements HandlerInterceptor { + + private static final String JWT_TOKEN_PREFIX = "Bearer "; + + private final JwtLoginProvider jwtLoginProvider; + + @Override + public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception { + String refreshToken = resolveAccessToken(request); + validateRefreshToken(refreshToken); + + return true; + } + + private void validateRefreshToken(String refreshToken) { + if (jwtLoginProvider.isExpiredToken(refreshToken)) { + throw new JwtExpiredTokenException(EXPIRED_TOKEN); + } + } + + private String resolveAccessToken(HttpServletRequest request) { + String token = request.getHeader(HttpHeaders.AUTHORIZATION); + validateToken(token); + return token.substring(JWT_TOKEN_PREFIX.length()); + } + + private void validateToken(String token) { + if (token == null) { + throw new JwtNoTokenException(TOKEN_NOT_FOUND); + } + if (!token.startsWith(JWT_TOKEN_PREFIX)) { + throw new JwtUnsupportedTokenException(UNSUPPORTED_TOKEN_TYPE); + } + } +} From 068ec5567f865f913eb41f63bbb58ff389e16dc7 Mon Sep 17 00:00:00 2001 From: seongjunnoh Date: Tue, 10 Sep 2024 14:07:41 +0900 Subject: [PATCH 09/26] =?UTF-8?q?Revert=20"feat=20:=20=EC=B9=B4=EC=B9=B4?= =?UTF-8?q?=EC=98=A4=20=EB=A1=9C=EA=B7=B8=EC=9D=B8=20=EC=8B=9C=20refresh?= =?UTF-8?q?=20token=20=EC=A0=95=EB=B3=B4=20db=EC=97=90=20=EC=A0=80?= =?UTF-8?q?=EC=9E=A5"?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit This reverts commit 2f56cfdcd492e64c8495e4758d5e07cdd11e4afb. --- .../java/space/space_spring/controller/OAuthController.java | 1 + .../space/space_spring/controller/ViewTestController.java | 1 - src/main/java/space/space_spring/service/OAuthService.java | 6 ------ 3 files changed, 1 insertion(+), 7 deletions(-) diff --git a/src/main/java/space/space_spring/controller/OAuthController.java b/src/main/java/space/space_spring/controller/OAuthController.java index 68011122..733021db 100644 --- a/src/main/java/space/space_spring/controller/OAuthController.java +++ b/src/main/java/space/space_spring/controller/OAuthController.java @@ -68,6 +68,7 @@ public void kakaoCallback(@RequestParam(name = "code") String code, HttpServletR // TODO 5. 카카오 로그인 유저에게 jwt 발급 TokenDTO tokenDTO = oAuthService.provideJwtToOAuthUser(userByOAuthInfo); + userByOAuthInfo.updateRefreshToken(tokenDTO.getRefreshToken()); System.out.println("tokenDTO.getAccessToken() = " + tokenDTO.getAccessToken()); System.out.println("tokenDTO.getRefreshToken() = " + tokenDTO.getRefreshToken()); diff --git a/src/main/java/space/space_spring/controller/ViewTestController.java b/src/main/java/space/space_spring/controller/ViewTestController.java index bb5c7509..327a225f 100644 --- a/src/main/java/space/space_spring/controller/ViewTestController.java +++ b/src/main/java/space/space_spring/controller/ViewTestController.java @@ -10,7 +10,6 @@ @Controller @Slf4j public class ViewTestController { - // RestController가 아니라 Controller 의 테스트가 필요할 경우 /** * 카카오 로그인 요청 처리 diff --git a/src/main/java/space/space_spring/service/OAuthService.java b/src/main/java/space/space_spring/service/OAuthService.java index cc4835cc..9d5d953a 100644 --- a/src/main/java/space/space_spring/service/OAuthService.java +++ b/src/main/java/space/space_spring/service/OAuthService.java @@ -105,16 +105,10 @@ public User findUserByOAuthInfo(KakaoInfo kakaoInfo) { return userUtils.findOrCreateUserForOAuthInfo(email, nickname, KAKAO); } - @Transactional public TokenDTO provideJwtToOAuthUser(User userByOAuthInfo) { - - // TODO 1. access token, refresh token 발급 String accessToken = jwtLoginProvider.generateToken(userByOAuthInfo, TokenType.ACCESS); String refreshToken = jwtLoginProvider.generateToken(userByOAuthInfo, TokenType.REFRESH); - // TODO 2. 카카오 로그인을 이용한 유저의 refresh token 정보 db에 저장 - userByOAuthInfo.updateRefreshToken(refreshToken); - return new TokenDTO(accessToken, refreshToken); } } From b2b1aa24c1d308292cfb560651287123c7509b15 Mon Sep 17 00:00:00 2001 From: seongjunnoh Date: Tue, 10 Sep 2024 14:23:40 +0900 Subject: [PATCH 10/26] =?UTF-8?q?feat=20:=20=EC=B9=B4=EC=B9=B4=EC=98=A4=20?= =?UTF-8?q?=EB=A1=9C=EA=B7=B8=EC=9D=B8=20=EC=8B=9C=20refresh=20token=20db?= =?UTF-8?q?=EC=97=90=20=EC=A0=80=EC=9E=A5=20&=20=EA=B8=B0=EC=A1=B4=20refre?= =?UTF-8?q?sh=20token=20=EC=9D=B8=ED=84=B0=EC=85=89=ED=84=B0=20=EC=BD=94?= =?UTF-8?q?=EB=93=9C=20=EC=82=AD=EC=A0=9C?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../space/space_spring/config/WebConfig.java | 12 +---- .../RefreshTokenInterceptorURL.java | 15 ------ .../controller/OAuthController.java | 4 +- .../refreshToken/RefreshTokenInterceptor.java | 52 ------------------- .../space_spring/jwt/JwtLoginProvider.java | 1 + .../space_spring/service/OAuthService.java | 5 ++ 6 files changed, 10 insertions(+), 79 deletions(-) delete mode 100644 src/main/java/space/space_spring/config/interceptorURL/RefreshTokenInterceptorURL.java delete mode 100644 src/main/java/space/space_spring/interceptor/refreshToken/RefreshTokenInterceptor.java diff --git a/src/main/java/space/space_spring/config/WebConfig.java b/src/main/java/space/space_spring/config/WebConfig.java index 1319ed6d..bde3eb1a 100644 --- a/src/main/java/space/space_spring/config/WebConfig.java +++ b/src/main/java/space/space_spring/config/WebConfig.java @@ -11,7 +11,6 @@ import space.space_spring.argumentResolver.userSpace.UserSpaceAuthHandlerArgumentResolver; import space.space_spring.argumentResolver.userSpace.UserSpaceIdHandlerArgumentResolver; import space.space_spring.config.interceptorURL.JwtLoginInterceptorURL; -import space.space_spring.config.interceptorURL.RefreshTokenInterceptorURL; import space.space_spring.config.interceptorURL.UserSpaceValidationInterceptorURL; import space.space_spring.interceptor.refreshToken.RefreshTokenInterceptor; import space.space_spring.interceptor.UserSpaceValidationInterceptor; @@ -25,7 +24,6 @@ public class WebConfig implements WebMvcConfigurer { private final JwtLoginAuthInterceptor jwtLoginAuthInterceptor; private final UserSpaceValidationInterceptor userSpaceValidationInterceptor; - private final RefreshTokenInterceptor refreshTokenInterceptor; private final JwtLoginAuthHandlerArgumentResolver jwtLoginAuthHandlerArgumentResolver; private final UserSpaceIdHandlerArgumentResolver userSpaceIdHandlerArgumentResolver; @@ -42,17 +40,9 @@ public void addInterceptors(InterceptorRegistry registry) { registration.addPathPatterns(interceptorURL.getUrlPattern()); } - InterceptorRegistration refreshTokenRegistration = - registry.addInterceptor(refreshTokenInterceptor) - .order(2); - - for (RefreshTokenInterceptorURL interceptorURL : RefreshTokenInterceptorURL.values()) { - registration.addPathPatterns(interceptorURL.getUrlPattern()); - } - InterceptorRegistration userSpaceRegistration = registry.addInterceptor(userSpaceValidationInterceptor) - .order(3); + .order(2); for(UserSpaceValidationInterceptorURL url:UserSpaceValidationInterceptorURL.values()) { userSpaceRegistration.addPathPatterns(url.getUrlPattern()); } diff --git a/src/main/java/space/space_spring/config/interceptorURL/RefreshTokenInterceptorURL.java b/src/main/java/space/space_spring/config/interceptorURL/RefreshTokenInterceptorURL.java deleted file mode 100644 index f3a3011a..00000000 --- a/src/main/java/space/space_spring/config/interceptorURL/RefreshTokenInterceptorURL.java +++ /dev/null @@ -1,15 +0,0 @@ -package space.space_spring.config.interceptorURL; - -import lombok.Getter; - -@Getter -public enum RefreshTokenInterceptorURL { - - ASK_NEW_ACCESS_TOKEN("/oauth/new-access-token"); - - private final String urlPattern; - - RefreshTokenInterceptorURL(String urlPattern) { - this.urlPattern = urlPattern; - } -} diff --git a/src/main/java/space/space_spring/controller/OAuthController.java b/src/main/java/space/space_spring/controller/OAuthController.java index 733021db..83f192ea 100644 --- a/src/main/java/space/space_spring/controller/OAuthController.java +++ b/src/main/java/space/space_spring/controller/OAuthController.java @@ -68,7 +68,9 @@ public void kakaoCallback(@RequestParam(name = "code") String code, HttpServletR // TODO 5. 카카오 로그인 유저에게 jwt 발급 TokenDTO tokenDTO = oAuthService.provideJwtToOAuthUser(userByOAuthInfo); - userByOAuthInfo.updateRefreshToken(tokenDTO.getRefreshToken()); + + // TODO 6. 카카오 로그인 유저에게 발급한 refresh token을 db에 저장 + oAuthService.updateRefreshToken(userByOAuthInfo, tokenDTO.getRefreshToken()); System.out.println("tokenDTO.getAccessToken() = " + tokenDTO.getAccessToken()); System.out.println("tokenDTO.getRefreshToken() = " + tokenDTO.getRefreshToken()); diff --git a/src/main/java/space/space_spring/interceptor/refreshToken/RefreshTokenInterceptor.java b/src/main/java/space/space_spring/interceptor/refreshToken/RefreshTokenInterceptor.java deleted file mode 100644 index b266cf9b..00000000 --- a/src/main/java/space/space_spring/interceptor/refreshToken/RefreshTokenInterceptor.java +++ /dev/null @@ -1,52 +0,0 @@ -package space.space_spring.interceptor.refreshToken; - -import jakarta.servlet.http.HttpServletRequest; -import jakarta.servlet.http.HttpServletResponse; -import lombok.RequiredArgsConstructor; -import org.springframework.http.HttpHeaders; -import org.springframework.stereotype.Component; -import org.springframework.web.servlet.HandlerInterceptor; -import space.space_spring.exception.jwt.bad_request.JwtNoTokenException; -import space.space_spring.exception.jwt.bad_request.JwtUnsupportedTokenException; -import space.space_spring.exception.jwt.unauthorized.JwtExpiredTokenException; -import space.space_spring.jwt.JwtLoginProvider; - -import static space.space_spring.response.status.BaseExceptionResponseStatus.*; - -@Component -@RequiredArgsConstructor -public class RefreshTokenInterceptor implements HandlerInterceptor { - - private static final String JWT_TOKEN_PREFIX = "Bearer "; - - private final JwtLoginProvider jwtLoginProvider; - - @Override - public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception { - String refreshToken = resolveAccessToken(request); - validateRefreshToken(refreshToken); - - return true; - } - - private void validateRefreshToken(String refreshToken) { - if (jwtLoginProvider.isExpiredToken(refreshToken)) { - throw new JwtExpiredTokenException(EXPIRED_TOKEN); - } - } - - private String resolveAccessToken(HttpServletRequest request) { - String token = request.getHeader(HttpHeaders.AUTHORIZATION); - validateToken(token); - return token.substring(JWT_TOKEN_PREFIX.length()); - } - - private void validateToken(String token) { - if (token == null) { - throw new JwtNoTokenException(TOKEN_NOT_FOUND); - } - if (!token.startsWith(JWT_TOKEN_PREFIX)) { - throw new JwtUnsupportedTokenException(UNSUPPORTED_TOKEN_TYPE); - } - } -} diff --git a/src/main/java/space/space_spring/jwt/JwtLoginProvider.java b/src/main/java/space/space_spring/jwt/JwtLoginProvider.java index 6d4ad5b7..a4577bf5 100644 --- a/src/main/java/space/space_spring/jwt/JwtLoginProvider.java +++ b/src/main/java/space/space_spring/jwt/JwtLoginProvider.java @@ -34,6 +34,7 @@ public String generateToken(User user, TokenType tokenType) { Long userId = user.getUserId(); + // refresh token의 경우에는 payload에 userId 값을 넣을 필요는 없어보이나 일단 이전 generateToken 메서드를 재활용 해보겠음 return Jwts.builder() // .setClaims(claims) .setIssuedAt(now) diff --git a/src/main/java/space/space_spring/service/OAuthService.java b/src/main/java/space/space_spring/service/OAuthService.java index 9d5d953a..451354dd 100644 --- a/src/main/java/space/space_spring/service/OAuthService.java +++ b/src/main/java/space/space_spring/service/OAuthService.java @@ -111,4 +111,9 @@ public TokenDTO provideJwtToOAuthUser(User userByOAuthInfo) { return new TokenDTO(accessToken, refreshToken); } + + @Transactional + public void updateRefreshToken(User user, String refreshToken) { + user.updateRefreshToken(refreshToken); + } } From e4563152c027f3b61933045d9e6808410bb50abc Mon Sep 17 00:00:00 2001 From: seongjunnoh Date: Tue, 10 Sep 2024 22:44:43 +0900 Subject: [PATCH 11/26] =?UTF-8?q?feat=20:=20access=20token=20=EA=B0=B1?= =?UTF-8?q?=EC=8B=A0=20=EC=9A=94=EC=B2=AD=20api=20=EC=BB=A8=ED=8A=B8?= =?UTF-8?q?=EB=A1=A4=EB=9F=AC=20=EC=BD=94=EB=93=9C=20=EC=B6=94=EA=B0=80?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../controller/OAuthController.java | 23 +++++++++++++++++++ .../java/space/space_spring/dao/UserDao.java | 13 +++++++++++ .../jwtLogin/JwtLoginAuthInterceptor.java | 18 ++++++++------- .../space_spring/jwt/JwtLoginProvider.java | 5 ++-- .../status/BaseExceptionResponseStatus.java | 1 + 5 files changed, 49 insertions(+), 11 deletions(-) diff --git a/src/main/java/space/space_spring/controller/OAuthController.java b/src/main/java/space/space_spring/controller/OAuthController.java index 83f192ea..6379ebf1 100644 --- a/src/main/java/space/space_spring/controller/OAuthController.java +++ b/src/main/java/space/space_spring/controller/OAuthController.java @@ -1,10 +1,12 @@ package space.space_spring.controller; import com.fasterxml.jackson.core.JsonProcessingException; +import jakarta.servlet.http.HttpServletRequest; import jakarta.servlet.http.HttpServletResponse; import lombok.RequiredArgsConstructor; import lombok.extern.slf4j.Slf4j; import org.springframework.beans.factory.annotation.Value; +import org.springframework.http.HttpHeaders; import org.springframework.web.bind.annotation.*; import space.space_spring.dto.jwt.TokenDTO; import space.space_spring.dto.oAuth.KakaoInfo; @@ -87,4 +89,25 @@ public void kakaoCallback(@RequestParam(name = "code") String code, HttpServletR response.sendRedirect(redirectUrl); } + + /** + * 엑세스 토큰 갱신 요청 처리 + * -> 엑세스 토큰, 리프레시 토큰 갱신 (RTR 패턴) + */ + @PostMapping("/new-token") + public BaseResponse updateAccessToken(HttpServletRequest request, HttpServletResponse response) throws IOException { + // request header 에서 refresh token 파싱 + String refreshToken = request.getHeader("Authorization-refresh"); + + // refresh token 유효성 검사 + oAuthService.validateRefreshToken(refreshToken); + + // access token, refresh token 새로 발급 + TokenDTO tokenDTO = oAuthService.updateTokenPair(refreshToken); + + // response header에 새로 발급한 token pair set + + // return + } + } diff --git a/src/main/java/space/space_spring/dao/UserDao.java b/src/main/java/space/space_spring/dao/UserDao.java index 8918331c..63c3b97e 100644 --- a/src/main/java/space/space_spring/dao/UserDao.java +++ b/src/main/java/space/space_spring/dao/UserDao.java @@ -8,6 +8,8 @@ import space.space_spring.entity.User; import space.space_spring.entity.enumStatus.UserSignupType; +import java.util.Optional; + @Repository public class UserDao { @@ -53,4 +55,15 @@ public User findUserByUserId(Long userId) { return em.find(User.class, userId); } + public Optional findUserByRefreshToken(String refreshToken) { + String jpql = "SELECT u FROM User u WHERE u.refreshToken = :refreshToken AND u.status = 'ACTIVE'"; + TypedQuery query = em.createQuery(jpql, User.class); + query.setParameter("refreshToken", refreshToken); + + try { + return Optional.of(query.getSingleResult()); + } catch (NoResultException e) { + return Optional.empty(); + } + } } diff --git a/src/main/java/space/space_spring/interceptor/jwtLogin/JwtLoginAuthInterceptor.java b/src/main/java/space/space_spring/interceptor/jwtLogin/JwtLoginAuthInterceptor.java index e61fa3fe..ba55bdf7 100644 --- a/src/main/java/space/space_spring/interceptor/jwtLogin/JwtLoginAuthInterceptor.java +++ b/src/main/java/space/space_spring/interceptor/jwtLogin/JwtLoginAuthInterceptor.java @@ -6,9 +6,12 @@ import org.springframework.http.HttpHeaders; import org.springframework.stereotype.Component; import org.springframework.web.servlet.HandlerInterceptor; +import space.space_spring.dao.UserDao; +import space.space_spring.exception.CustomException; import space.space_spring.exception.jwt.bad_request.JwtNoTokenException; import space.space_spring.exception.jwt.bad_request.JwtUnsupportedTokenException; import space.space_spring.exception.jwt.unauthorized.JwtExpiredTokenException; +import space.space_spring.exception.jwt.unauthorized.JwtInvalidTokenException; import space.space_spring.jwt.JwtLoginProvider; import static space.space_spring.response.status.BaseExceptionResponseStatus.*; @@ -23,22 +26,21 @@ public class JwtLoginAuthInterceptor implements HandlerInterceptor{ @Override public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception { + // TODO 1. request header에서 access token 파싱 String accessToken = resolveAccessToken(request); - validateAccessToken(accessToken); - // jwt에서 userId get + // TODO 2. AT 유효성 검사 + if (jwtLoginProvider.isExpiredToken(accessToken)) { + throw new JwtExpiredTokenException(EXPIRED_TOKEN); + } + + // TODO 3. AT 의 payload 로 부터 userId 값 get Long userIdFromToken = jwtLoginProvider.getUserIdFromToken(accessToken); request.setAttribute("userId", userIdFromToken); return true; } - private void validateAccessToken(String accessToken) { - if (jwtLoginProvider.isExpiredToken(accessToken)) { - throw new JwtExpiredTokenException(EXPIRED_TOKEN); - } - } - private String resolveAccessToken(HttpServletRequest request) { String token = request.getHeader(HttpHeaders.AUTHORIZATION); validateToken(token); diff --git a/src/main/java/space/space_spring/jwt/JwtLoginProvider.java b/src/main/java/space/space_spring/jwt/JwtLoginProvider.java index a4577bf5..f5847575 100644 --- a/src/main/java/space/space_spring/jwt/JwtLoginProvider.java +++ b/src/main/java/space/space_spring/jwt/JwtLoginProvider.java @@ -34,7 +34,6 @@ public String generateToken(User user, TokenType tokenType) { Long userId = user.getUserId(); - // refresh token의 경우에는 payload에 userId 값을 넣을 필요는 없어보이나 일단 이전 generateToken 메서드를 재활용 해보겠음 return Jwts.builder() // .setClaims(claims) .setIssuedAt(now) @@ -54,11 +53,11 @@ private Date setExpiration(Date now, TokenType tokenType) { return new Date(now.getTime() + JWT_EXPIRED_IN * times); } - public boolean isExpiredToken(String accessToken) { + public boolean isExpiredToken(String token) { try { Jws claims = Jwts.parserBuilder() .setSigningKey(JWT_LOGIN_SECRET_KEY).build() - .parseClaimsJws(accessToken); + .parseClaimsJws(token); return claims.getBody().getExpiration().before(new Date()); } catch (ExpiredJwtException e) { diff --git a/src/main/java/space/space_spring/response/status/BaseExceptionResponseStatus.java b/src/main/java/space/space_spring/response/status/BaseExceptionResponseStatus.java index 7fdf826c..928e88a0 100644 --- a/src/main/java/space/space_spring/response/status/BaseExceptionResponseStatus.java +++ b/src/main/java/space/space_spring/response/status/BaseExceptionResponseStatus.java @@ -42,6 +42,7 @@ public enum BaseExceptionResponseStatus implements ResponseStatus { TOKEN_MISMATCH(4006, HttpStatus.UNAUTHORIZED, "로그인 정보가 토큰 정보와 일치하지 않습니다."), CANNOT_FIND_USER_ID(4007, HttpStatus.UNAUTHORIZED,"토큰의 userId정보를 찾을 수 없습니다."), WRONG_SIGNATURE_JWT(4008,HttpStatus.UNAUTHORIZED,"JWT 서명이 잘못 되었습니다."), + EXPIRED_REFRESH_TOKEN(4009, HttpStatus.UNAUTHORIZED, "만료된 리프레시 토큰입니다. 다시 로그인해야합니다."), /** * 5000: User 오류 From 565d4cdf42cde5cbce3bff7434b8ca3faee2e601 Mon Sep 17 00:00:00 2001 From: seongjunnoh Date: Tue, 10 Sep 2024 23:01:11 +0900 Subject: [PATCH 12/26] =?UTF-8?q?feat=20:=20access=20token=20=EA=B0=B1?= =?UTF-8?q?=EC=8B=A0=20=EC=9A=94=EC=B2=AD=20api?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../controller/OAuthController.java | 6 +++ .../space_spring/jwt/JwtLoginProvider.java | 4 +- .../space_spring/service/OAuthService.java | 38 +++++++++++++++++++ 3 files changed, 46 insertions(+), 2 deletions(-) diff --git a/src/main/java/space/space_spring/controller/OAuthController.java b/src/main/java/space/space_spring/controller/OAuthController.java index 6379ebf1..ff8ae355 100644 --- a/src/main/java/space/space_spring/controller/OAuthController.java +++ b/src/main/java/space/space_spring/controller/OAuthController.java @@ -106,8 +106,14 @@ public BaseResponse updateAccessToken(HttpServletRequest request, HttpSe TokenDTO tokenDTO = oAuthService.updateTokenPair(refreshToken); // response header에 새로 발급한 token pair set + response.setHeader("Authorization-refresh", "Bearer " + tokenDTO.getRefreshToken()); + response.setHeader("Authorization", "Bearer " + tokenDTO.getAccessToken()); + System.out.println("tokenDTO.getAccessToken() = " + tokenDTO.getAccessToken()); + System.out.println("tokenDTO.getRefreshToken() = " + tokenDTO.getRefreshToken()); + // return + return new BaseResponse<>("토큰 갱신 요청 성공"); } } diff --git a/src/main/java/space/space_spring/jwt/JwtLoginProvider.java b/src/main/java/space/space_spring/jwt/JwtLoginProvider.java index f5847575..d0953f68 100644 --- a/src/main/java/space/space_spring/jwt/JwtLoginProvider.java +++ b/src/main/java/space/space_spring/jwt/JwtLoginProvider.java @@ -78,11 +78,11 @@ public boolean isExpiredToken(String token) { } - public Long getUserIdFromToken(String accessToken) { + public Long getUserIdFromToken(String token) { try { Jws claims = Jwts.parserBuilder() .setSigningKey(JWT_LOGIN_SECRET_KEY).build() - .parseClaimsJws(accessToken); + .parseClaimsJws(token); return claims.getBody().get("userId", Long.class); } catch (JwtException e) { log.error("[JwtTokenProvider.getJwtPayloadDtoFromToken]", e); diff --git a/src/main/java/space/space_spring/service/OAuthService.java b/src/main/java/space/space_spring/service/OAuthService.java index 451354dd..790af767 100644 --- a/src/main/java/space/space_spring/service/OAuthService.java +++ b/src/main/java/space/space_spring/service/OAuthService.java @@ -13,14 +13,19 @@ import org.springframework.util.LinkedMultiValueMap; import org.springframework.util.MultiValueMap; import org.springframework.web.client.RestTemplate; +import space.space_spring.dao.UserDao; import space.space_spring.dto.jwt.TokenDTO; import space.space_spring.dto.jwt.TokenType; import space.space_spring.dto.oAuth.KakaoInfo; import space.space_spring.entity.User; +import space.space_spring.exception.jwt.unauthorized.JwtExpiredTokenException; +import space.space_spring.exception.jwt.unauthorized.JwtInvalidTokenException; import space.space_spring.jwt.JwtLoginProvider; import space.space_spring.util.user.UserUtils; import static space.space_spring.entity.enumStatus.UserSignupType.KAKAO; +import static space.space_spring.response.status.BaseExceptionResponseStatus.EXPIRED_REFRESH_TOKEN; +import static space.space_spring.response.status.BaseExceptionResponseStatus.INVALID_TOKEN; @Service @RequiredArgsConstructor @@ -28,6 +33,7 @@ public class OAuthService { private final UserUtils userUtils; private final JwtLoginProvider jwtLoginProvider; + private final UserDao userDao; /** * 카카오 인증 서버가 전달해준 유저의 인가코드로 토큰 발급 요청 @@ -116,4 +122,36 @@ public TokenDTO provideJwtToOAuthUser(User userByOAuthInfo) { public void updateRefreshToken(User user, String refreshToken) { user.updateRefreshToken(refreshToken); } + + @Transactional + public void validateRefreshToken(String refreshToken) { + // TODO 1. refresh token의 만료시간 체크 + if (jwtLoginProvider.isExpiredToken(refreshToken)) { + // refresh token이 만료된 경우 -> 예외 발생 -> 유저의 재 로그인 유도 + throw new JwtExpiredTokenException(EXPIRED_REFRESH_TOKEN); + } + + // TODO 2. refresh token이 db에 실제로 존재하는지 체크 + if (userDao.findUserByRefreshToken(refreshToken).isEmpty()) { + // refresh token이 db에 존재하지 않느 경우 -> 유효하지 않은 refresh token이므로 예외 발생 + throw new JwtInvalidTokenException(INVALID_TOKEN); + } + } + + public TokenDTO updateTokenPair(String refreshToken) { + // TODO 1. refresh token으로 user find + Long userIdFromToken = jwtLoginProvider.getUserIdFromToken(refreshToken); + User userByUserId = userUtils.findUserByUserId(userIdFromToken); + + // TODO 2. new access token, refresh token 발급 + String newAccessToken = jwtLoginProvider.generateToken(userByUserId, TokenType.ACCESS); + String newRefreshToken = jwtLoginProvider.generateToken(userByUserId, TokenType.REFRESH); + + // TODO 3. db의 refresh token update + userByUserId.updateRefreshToken(newRefreshToken); + + // TODO 4. return + return new TokenDTO(newAccessToken, newRefreshToken); + } + } From c705e48ba0b9e814cfaddf2b25480b5fa0006bd4 Mon Sep 17 00:00:00 2001 From: seongjunnoh Date: Tue, 10 Sep 2024 23:22:16 +0900 Subject: [PATCH 13/26] =?UTF-8?q?refactor=20:=20access=20token,=20refresh?= =?UTF-8?q?=20token=20=EC=83=9D=EC=84=B1=EC=8B=9C=20=EB=A7=8C=EB=A3=8C?= =?UTF-8?q?=EC=8B=9C=EA=B0=84=20value=20=EB=B6=84=EB=A6=AC?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../java/space/space_spring/config/WebConfig.java | 1 - .../space/space_spring/controller/UserController.java | 3 +++ .../java/space/space_spring/jwt/JwtLoginProvider.java | 11 ++++++----- 3 files changed, 9 insertions(+), 6 deletions(-) diff --git a/src/main/java/space/space_spring/config/WebConfig.java b/src/main/java/space/space_spring/config/WebConfig.java index bde3eb1a..6676d459 100644 --- a/src/main/java/space/space_spring/config/WebConfig.java +++ b/src/main/java/space/space_spring/config/WebConfig.java @@ -12,7 +12,6 @@ import space.space_spring.argumentResolver.userSpace.UserSpaceIdHandlerArgumentResolver; import space.space_spring.config.interceptorURL.JwtLoginInterceptorURL; import space.space_spring.config.interceptorURL.UserSpaceValidationInterceptorURL; -import space.space_spring.interceptor.refreshToken.RefreshTokenInterceptor; import space.space_spring.interceptor.UserSpaceValidationInterceptor; import space.space_spring.interceptor.jwtLogin.JwtLoginAuthInterceptor; diff --git a/src/main/java/space/space_spring/controller/UserController.java b/src/main/java/space/space_spring/controller/UserController.java index ce827fc0..de0843d8 100644 --- a/src/main/java/space/space_spring/controller/UserController.java +++ b/src/main/java/space/space_spring/controller/UserController.java @@ -57,6 +57,9 @@ public BaseResponse login(@Validated @RequestBody PostLog PostLoginDto login = userService.login(request); + System.out.println("login.getTokenDTO().getRefreshToken() = " + login.getTokenDTO().getRefreshToken()); + System.out.println("login.getTokenDTO().getAccessToken() = " + login.getTokenDTO().getAccessToken()); + response.setHeader("Authorization-refresh", "Bearer " + login.getTokenDTO().getRefreshToken()); response.setHeader("Authorization", "Bearer " + login.getTokenDTO().getAccessToken()); diff --git a/src/main/java/space/space_spring/jwt/JwtLoginProvider.java b/src/main/java/space/space_spring/jwt/JwtLoginProvider.java index d0953f68..301a8f0b 100644 --- a/src/main/java/space/space_spring/jwt/JwtLoginProvider.java +++ b/src/main/java/space/space_spring/jwt/JwtLoginProvider.java @@ -21,10 +21,11 @@ public class JwtLoginProvider { @Value("${secret.jwt-login-secret-key}") private String JWT_LOGIN_SECRET_KEY; - @Value("${secret.jwt-expired-in}") - private Long JWT_EXPIRED_IN; + @Value("${secret.access-expired-in}") + private Long ACCESS_EXPIRED_IN; - private static int times = 168; // 1시간 * times == refresh token 만료 시간 + @Value("${secret.refresh-expired-in}") + private Long REFRESH_EXPIRED_IN; public String generateToken(User user, TokenType tokenType) { // Claims claims = Jwts.claims().setSubject(jwtPayloadDto.getUserId().toString()); @@ -46,11 +47,11 @@ public String generateToken(User user, TokenType tokenType) { private Date setExpiration(Date now, TokenType tokenType) { if (tokenType.equals(TokenType.ACCESS)) { // 엑세스 토큰 : 1시간 - return new Date(now.getTime() + JWT_EXPIRED_IN); + return new Date(now.getTime() + ACCESS_EXPIRED_IN); } // 리프레쉬 토큰 : 7일 - return new Date(now.getTime() + JWT_EXPIRED_IN * times); + return new Date(now.getTime() + REFRESH_EXPIRED_IN); } public boolean isExpiredToken(String token) { From a704a7e761924cbb4dcc9aea0c4de40b5485e671 Mon Sep 17 00:00:00 2001 From: seongjunnoh Date: Wed, 11 Sep 2024 00:46:14 +0900 Subject: [PATCH 14/26] =?UTF-8?q?fix=20:=20access=20token,=20refresh=20tok?= =?UTF-8?q?en=20=EC=8B=9C=ED=81=AC=EB=A6=BF=ED=82=A4=20=EB=B6=84=EB=A6=AC?= =?UTF-8?q?=20&=20=EA=B7=B8=EC=97=90=EB=94=B0=EB=A5=B8=20=EC=BD=94?= =?UTF-8?q?=EB=93=9C=20=EC=88=98=EC=A0=95?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../jwtLogin/JwtLoginAuthInterceptor.java | 7 +++-- .../jwtSocket/JwtChannelInterceptor.java | 7 +++-- .../space_spring/jwt/JwtLoginProvider.java | 30 +++++++++++++------ .../status/BaseExceptionResponseStatus.java | 4 +-- .../space_spring/service/OAuthService.java | 4 +-- 5 files changed, 33 insertions(+), 19 deletions(-) diff --git a/src/main/java/space/space_spring/interceptor/jwtLogin/JwtLoginAuthInterceptor.java b/src/main/java/space/space_spring/interceptor/jwtLogin/JwtLoginAuthInterceptor.java index ba55bdf7..7522cf31 100644 --- a/src/main/java/space/space_spring/interceptor/jwtLogin/JwtLoginAuthInterceptor.java +++ b/src/main/java/space/space_spring/interceptor/jwtLogin/JwtLoginAuthInterceptor.java @@ -7,6 +7,7 @@ import org.springframework.stereotype.Component; import org.springframework.web.servlet.HandlerInterceptor; import space.space_spring.dao.UserDao; +import space.space_spring.dto.jwt.TokenType; import space.space_spring.exception.CustomException; import space.space_spring.exception.jwt.bad_request.JwtNoTokenException; import space.space_spring.exception.jwt.bad_request.JwtUnsupportedTokenException; @@ -30,12 +31,12 @@ public boolean preHandle(HttpServletRequest request, HttpServletResponse respons String accessToken = resolveAccessToken(request); // TODO 2. AT 유효성 검사 - if (jwtLoginProvider.isExpiredToken(accessToken)) { - throw new JwtExpiredTokenException(EXPIRED_TOKEN); + if (jwtLoginProvider.isExpiredToken(accessToken, TokenType.ACCESS)) { + throw new JwtExpiredTokenException(EXPIRED_ACCESS_TOKEN); } // TODO 3. AT 의 payload 로 부터 userId 값 get - Long userIdFromToken = jwtLoginProvider.getUserIdFromToken(accessToken); + Long userIdFromToken = jwtLoginProvider.getUserIdFromToken(accessToken, TokenType.ACCESS); request.setAttribute("userId", userIdFromToken); return true; diff --git a/src/main/java/space/space_spring/interceptor/jwtSocket/JwtChannelInterceptor.java b/src/main/java/space/space_spring/interceptor/jwtSocket/JwtChannelInterceptor.java index 38bad767..e2738886 100644 --- a/src/main/java/space/space_spring/interceptor/jwtSocket/JwtChannelInterceptor.java +++ b/src/main/java/space/space_spring/interceptor/jwtSocket/JwtChannelInterceptor.java @@ -8,6 +8,7 @@ import org.springframework.messaging.simp.stomp.StompHeaderAccessor; import org.springframework.messaging.support.ChannelInterceptor; import org.springframework.stereotype.Component; +import space.space_spring.dto.jwt.TokenType; import space.space_spring.exception.jwt.bad_request.JwtNoTokenException; import space.space_spring.exception.jwt.bad_request.JwtUnsupportedTokenException; import space.space_spring.exception.jwt.unauthorized.JwtExpiredTokenException; @@ -32,7 +33,7 @@ public Message preSend(Message message, MessageChannel channel) { String validatedToken = validateAccessToken(jwtToken); // 검증 후 사용자 정보를 세션에 저장 - Long userId = jwtLoginProvider.getUserIdFromToken(validatedToken); + Long userId = jwtLoginProvider.getUserIdFromToken(validatedToken, TokenType.ACCESS); accessor.getSessionAttributes().put("userId", userId); } return message; @@ -51,8 +52,8 @@ private String validateAccessToken(String token) { String tokenWithoutPrefix = token.substring(JWT_TOKEN_PREFIX.length()); // access token 값 validate - if (jwtLoginProvider.isExpiredToken(tokenWithoutPrefix)) { - throw new JwtExpiredTokenException(EXPIRED_TOKEN); + if (jwtLoginProvider.isExpiredToken(tokenWithoutPrefix, TokenType.ACCESS)) { + throw new JwtExpiredTokenException(EXPIRED_ACCESS_TOKEN); } return tokenWithoutPrefix; diff --git a/src/main/java/space/space_spring/jwt/JwtLoginProvider.java b/src/main/java/space/space_spring/jwt/JwtLoginProvider.java index 301a8f0b..99aa7052 100644 --- a/src/main/java/space/space_spring/jwt/JwtLoginProvider.java +++ b/src/main/java/space/space_spring/jwt/JwtLoginProvider.java @@ -18,8 +18,11 @@ @Slf4j @Component public class JwtLoginProvider { - @Value("${secret.jwt-login-secret-key}") - private String JWT_LOGIN_SECRET_KEY; + @Value("${secret.access-secret-key}") + private String ACCESS_SECRET_KEY; + + @Value("${secret.refresh-secret-key}") + private String REFRESH_SECRET_KEY; @Value("${secret.access-expired-in}") private Long ACCESS_EXPIRED_IN; @@ -40,10 +43,19 @@ public String generateToken(User user, TokenType tokenType) { .setIssuedAt(now) .setExpiration(expiration) .claim("userId", userId) - .signWith(SignatureAlgorithm.HS256, JWT_LOGIN_SECRET_KEY) + .signWith(SignatureAlgorithm.HS256, choiceSecretKey(tokenType)) .compact(); } + private String choiceSecretKey(TokenType tokenType) { + if (tokenType.equals(TokenType.ACCESS)) { + System.out.println("access token : " + ACCESS_SECRET_KEY); + return ACCESS_SECRET_KEY; + } + System.out.println("refresh token : " + REFRESH_SECRET_KEY); + return REFRESH_SECRET_KEY; + } + private Date setExpiration(Date now, TokenType tokenType) { if (tokenType.equals(TokenType.ACCESS)) { // 엑세스 토큰 : 1시간 @@ -54,17 +66,17 @@ private Date setExpiration(Date now, TokenType tokenType) { return new Date(now.getTime() + REFRESH_EXPIRED_IN); } - public boolean isExpiredToken(String token) { + public boolean isExpiredToken(String token, TokenType tokenType) { try { Jws claims = Jwts.parserBuilder() - .setSigningKey(JWT_LOGIN_SECRET_KEY).build() + .setSigningKey(choiceSecretKey(tokenType)).build() .parseClaimsJws(token); return claims.getBody().getExpiration().before(new Date()); } catch (ExpiredJwtException e) { return true; - }catch (UnsupportedJwtException e) { + } catch (UnsupportedJwtException e) { throw new JwtUnsupportedTokenException(UNSUPPORTED_TOKEN_TYPE); } catch (MalformedJwtException e) { throw new JwtMalformedTokenException(MALFORMED_TOKEN); @@ -72,17 +84,17 @@ public boolean isExpiredToken(String token) { throw new JwtInvalidTokenException(INVALID_TOKEN); } catch (SignatureException e){ throw new CustomException(WRONG_SIGNATURE_JWT); - }catch (JwtException e) { + } catch (JwtException e) { log.error("[JwtTokenProvider.validateAccessToken]", e); throw e; } } - public Long getUserIdFromToken(String token) { + public Long getUserIdFromToken(String token, TokenType tokenType) { try { Jws claims = Jwts.parserBuilder() - .setSigningKey(JWT_LOGIN_SECRET_KEY).build() + .setSigningKey(choiceSecretKey(tokenType)).build() .parseClaimsJws(token); return claims.getBody().get("userId", Long.class); } catch (JwtException e) { diff --git a/src/main/java/space/space_spring/response/status/BaseExceptionResponseStatus.java b/src/main/java/space/space_spring/response/status/BaseExceptionResponseStatus.java index 928e88a0..b572d313 100644 --- a/src/main/java/space/space_spring/response/status/BaseExceptionResponseStatus.java +++ b/src/main/java/space/space_spring/response/status/BaseExceptionResponseStatus.java @@ -38,11 +38,11 @@ public enum BaseExceptionResponseStatus implements ResponseStatus { UNSUPPORTED_TOKEN_TYPE(4002, HttpStatus.UNAUTHORIZED, "지원되지 않는 토큰 형식입니다."), INVALID_TOKEN(4003, HttpStatus.UNAUTHORIZED, "유효하지 않은 토큰입니다."), MALFORMED_TOKEN(4004, HttpStatus.UNAUTHORIZED, "토큰이 올바르게 구성되지 않았습니다."), - EXPIRED_TOKEN(4005, HttpStatus.UNAUTHORIZED, "만료된 토큰입니다."), + EXPIRED_ACCESS_TOKEN(4005, HttpStatus.UNAUTHORIZED, "만료된 access token 입니다."), TOKEN_MISMATCH(4006, HttpStatus.UNAUTHORIZED, "로그인 정보가 토큰 정보와 일치하지 않습니다."), CANNOT_FIND_USER_ID(4007, HttpStatus.UNAUTHORIZED,"토큰의 userId정보를 찾을 수 없습니다."), WRONG_SIGNATURE_JWT(4008,HttpStatus.UNAUTHORIZED,"JWT 서명이 잘못 되었습니다."), - EXPIRED_REFRESH_TOKEN(4009, HttpStatus.UNAUTHORIZED, "만료된 리프레시 토큰입니다. 다시 로그인해야합니다."), + EXPIRED_REFRESH_TOKEN(4009, HttpStatus.UNAUTHORIZED, "만료된 refresh token 입니다. 다시 로그인해야합니다."), /** * 5000: User 오류 diff --git a/src/main/java/space/space_spring/service/OAuthService.java b/src/main/java/space/space_spring/service/OAuthService.java index 790af767..674d44a3 100644 --- a/src/main/java/space/space_spring/service/OAuthService.java +++ b/src/main/java/space/space_spring/service/OAuthService.java @@ -126,7 +126,7 @@ public void updateRefreshToken(User user, String refreshToken) { @Transactional public void validateRefreshToken(String refreshToken) { // TODO 1. refresh token의 만료시간 체크 - if (jwtLoginProvider.isExpiredToken(refreshToken)) { + if (jwtLoginProvider.isExpiredToken(refreshToken, TokenType.REFRESH)) { // refresh token이 만료된 경우 -> 예외 발생 -> 유저의 재 로그인 유도 throw new JwtExpiredTokenException(EXPIRED_REFRESH_TOKEN); } @@ -140,7 +140,7 @@ public void validateRefreshToken(String refreshToken) { public TokenDTO updateTokenPair(String refreshToken) { // TODO 1. refresh token으로 user find - Long userIdFromToken = jwtLoginProvider.getUserIdFromToken(refreshToken); + Long userIdFromToken = jwtLoginProvider.getUserIdFromToken(refreshToken, TokenType.REFRESH); User userByUserId = userUtils.findUserByUserId(userIdFromToken); // TODO 2. new access token, refresh token 발급 From 06b53d4f80d792021260b7ab79927845f8ac1c3b Mon Sep 17 00:00:00 2001 From: seongjunnoh Date: Wed, 11 Sep 2024 01:58:19 +0900 Subject: [PATCH 15/26] =?UTF-8?q?fix=20:=20=EB=A1=9C=EA=B7=B8=EC=9D=B8=20?= =?UTF-8?q?=EC=8B=9C=20access=20token,=20refresh=20token=20=EC=84=9C?= =?UTF-8?q?=EB=A1=9C=20=EB=B0=98=EB=8C=80=EB=A1=9C=20=ED=97=A4=EB=8D=94?= =?UTF-8?q?=EC=97=90=20=EC=A3=BC=EC=9E=85=EB=90=98=EB=8A=94=20=EC=97=90?= =?UTF-8?q?=EB=9F=AC=20=ED=95=B4=EA=B2=B0?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/main/java/space/space_spring/dto/jwt/TokenDTO.java | 2 ++ src/main/java/space/space_spring/jwt/JwtLoginProvider.java | 3 +-- src/main/java/space/space_spring/service/UserService.java | 4 ++-- 3 files changed, 5 insertions(+), 4 deletions(-) diff --git a/src/main/java/space/space_spring/dto/jwt/TokenDTO.java b/src/main/java/space/space_spring/dto/jwt/TokenDTO.java index 8cb7d1f0..9dca7de7 100644 --- a/src/main/java/space/space_spring/dto/jwt/TokenDTO.java +++ b/src/main/java/space/space_spring/dto/jwt/TokenDTO.java @@ -1,12 +1,14 @@ package space.space_spring.dto.jwt; import lombok.AllArgsConstructor; +import lombok.Builder; import lombok.Getter; import lombok.NoArgsConstructor; @Getter @NoArgsConstructor @AllArgsConstructor +@Builder public class TokenDTO { private String refreshToken; diff --git a/src/main/java/space/space_spring/jwt/JwtLoginProvider.java b/src/main/java/space/space_spring/jwt/JwtLoginProvider.java index 99aa7052..f1ef0ed8 100644 --- a/src/main/java/space/space_spring/jwt/JwtLoginProvider.java +++ b/src/main/java/space/space_spring/jwt/JwtLoginProvider.java @@ -49,10 +49,8 @@ public String generateToken(User user, TokenType tokenType) { private String choiceSecretKey(TokenType tokenType) { if (tokenType.equals(TokenType.ACCESS)) { - System.out.println("access token : " + ACCESS_SECRET_KEY); return ACCESS_SECRET_KEY; } - System.out.println("refresh token : " + REFRESH_SECRET_KEY); return REFRESH_SECRET_KEY; } @@ -83,6 +81,7 @@ public boolean isExpiredToken(String token, TokenType tokenType) { } catch (IllegalArgumentException e) { throw new JwtInvalidTokenException(INVALID_TOKEN); } catch (SignatureException e){ + log.error("비밀키 : " + choiceSecretKey(tokenType)); throw new CustomException(WRONG_SIGNATURE_JWT); } catch (JwtException e) { log.error("[JwtTokenProvider.validateAccessToken]", e); diff --git a/src/main/java/space/space_spring/service/UserService.java b/src/main/java/space/space_spring/service/UserService.java index 8ce63489..836c3a28 100644 --- a/src/main/java/space/space_spring/service/UserService.java +++ b/src/main/java/space/space_spring/service/UserService.java @@ -77,8 +77,8 @@ public PostLoginDto login(PostLoginDto.Request request) { // TODO 4. refresh token db에 저장 userByEmail.updateRefreshToken(refreshToken); - return new PostLoginDto ( - new TokenDTO(accessToken, refreshToken), + return new PostLoginDto( + new TokenDTO(refreshToken, accessToken), userByEmail.getUserId() ); } From f5df44e66cd4789bfbefd1a93bf666bbe25bf4a6 Mon Sep 17 00:00:00 2001 From: seongjunnoh Date: Wed, 11 Sep 2024 02:21:46 +0900 Subject: [PATCH 16/26] =?UTF-8?q?fix=20:=20=EC=97=91=EC=84=B8=EC=8A=A4=20?= =?UTF-8?q?=ED=86=A0=ED=81=B0=20=EA=B0=B1=EC=8B=A0=20=EC=9A=94=EC=B2=AD=20?= =?UTF-8?q?=ED=97=A4=EB=8D=94=EC=9D=98=20refresh=20token=20=ED=8C=8C?= =?UTF-8?q?=EC=8B=B1=20=EC=97=90=EB=9F=AC=20=EC=88=98=EC=A0=95?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../controller/OAuthController.java | 5 ++-- .../space_spring/jwt/JwtLoginProvider.java | 1 - .../space_spring/service/OAuthService.java | 29 +++++++++++++++++-- 3 files changed, 28 insertions(+), 7 deletions(-) diff --git a/src/main/java/space/space_spring/controller/OAuthController.java b/src/main/java/space/space_spring/controller/OAuthController.java index ff8ae355..fb389cec 100644 --- a/src/main/java/space/space_spring/controller/OAuthController.java +++ b/src/main/java/space/space_spring/controller/OAuthController.java @@ -96,8 +96,8 @@ public void kakaoCallback(@RequestParam(name = "code") String code, HttpServletR */ @PostMapping("/new-token") public BaseResponse updateAccessToken(HttpServletRequest request, HttpServletResponse response) throws IOException { - // request header 에서 refresh token 파싱 - String refreshToken = request.getHeader("Authorization-refresh"); + // refresh token 파싱 + String refreshToken = oAuthService.resolveRefreshToken(request); // refresh token 유효성 검사 oAuthService.validateRefreshToken(refreshToken); @@ -115,5 +115,4 @@ public BaseResponse updateAccessToken(HttpServletRequest request, HttpSe // return return new BaseResponse<>("토큰 갱신 요청 성공"); } - } diff --git a/src/main/java/space/space_spring/jwt/JwtLoginProvider.java b/src/main/java/space/space_spring/jwt/JwtLoginProvider.java index f1ef0ed8..748d0e13 100644 --- a/src/main/java/space/space_spring/jwt/JwtLoginProvider.java +++ b/src/main/java/space/space_spring/jwt/JwtLoginProvider.java @@ -81,7 +81,6 @@ public boolean isExpiredToken(String token, TokenType tokenType) { } catch (IllegalArgumentException e) { throw new JwtInvalidTokenException(INVALID_TOKEN); } catch (SignatureException e){ - log.error("비밀키 : " + choiceSecretKey(tokenType)); throw new CustomException(WRONG_SIGNATURE_JWT); } catch (JwtException e) { log.error("[JwtTokenProvider.validateAccessToken]", e); diff --git a/src/main/java/space/space_spring/service/OAuthService.java b/src/main/java/space/space_spring/service/OAuthService.java index 674d44a3..ba0fa4fb 100644 --- a/src/main/java/space/space_spring/service/OAuthService.java +++ b/src/main/java/space/space_spring/service/OAuthService.java @@ -3,6 +3,7 @@ import com.fasterxml.jackson.core.JsonProcessingException; import com.fasterxml.jackson.databind.JsonNode; import com.fasterxml.jackson.databind.ObjectMapper; +import jakarta.servlet.http.HttpServletRequest; import lombok.RequiredArgsConstructor; import org.springframework.http.HttpEntity; import org.springframework.http.HttpHeaders; @@ -18,14 +19,16 @@ import space.space_spring.dto.jwt.TokenType; import space.space_spring.dto.oAuth.KakaoInfo; import space.space_spring.entity.User; +import space.space_spring.exception.jwt.bad_request.JwtNoTokenException; +import space.space_spring.exception.jwt.bad_request.JwtUnsupportedTokenException; import space.space_spring.exception.jwt.unauthorized.JwtExpiredTokenException; import space.space_spring.exception.jwt.unauthorized.JwtInvalidTokenException; import space.space_spring.jwt.JwtLoginProvider; import space.space_spring.util.user.UserUtils; import static space.space_spring.entity.enumStatus.UserSignupType.KAKAO; -import static space.space_spring.response.status.BaseExceptionResponseStatus.EXPIRED_REFRESH_TOKEN; -import static space.space_spring.response.status.BaseExceptionResponseStatus.INVALID_TOKEN; +import static space.space_spring.response.status.BaseExceptionResponseStatus.*; +import static space.space_spring.response.status.BaseExceptionResponseStatus.UNSUPPORTED_TOKEN_TYPE; @Service @RequiredArgsConstructor @@ -35,6 +38,9 @@ public class OAuthService { private final JwtLoginProvider jwtLoginProvider; private final UserDao userDao; + private static final String JWT_TOKEN_PREFIX = "Bearer "; + + /** * 카카오 인증 서버가 전달해준 유저의 인가코드로 토큰 발급 요청 */ @@ -123,6 +129,22 @@ public void updateRefreshToken(User user, String refreshToken) { user.updateRefreshToken(refreshToken); } + public String resolveRefreshToken(HttpServletRequest request) { + String token = request.getHeader("Authorization-refresh"); + validateToken(token); + return token.substring(JWT_TOKEN_PREFIX.length()); + + } + + private void validateToken(String token) { + if (token == null) { + throw new JwtNoTokenException(TOKEN_NOT_FOUND); + } + if (!token.startsWith(JWT_TOKEN_PREFIX)) { + throw new JwtUnsupportedTokenException(UNSUPPORTED_TOKEN_TYPE); + } + } + @Transactional public void validateRefreshToken(String refreshToken) { // TODO 1. refresh token의 만료시간 체크 @@ -138,6 +160,7 @@ public void validateRefreshToken(String refreshToken) { } } + @Transactional public TokenDTO updateTokenPair(String refreshToken) { // TODO 1. refresh token으로 user find Long userIdFromToken = jwtLoginProvider.getUserIdFromToken(refreshToken, TokenType.REFRESH); @@ -151,7 +174,7 @@ public TokenDTO updateTokenPair(String refreshToken) { userByUserId.updateRefreshToken(newRefreshToken); // TODO 4. return - return new TokenDTO(newAccessToken, newRefreshToken); + return new TokenDTO(newRefreshToken, newAccessToken); } } From 2c42a77e10f19e4ffd05253a14ec415f52dc356b Mon Sep 17 00:00:00 2001 From: seongjunnoh Date: Wed, 11 Sep 2024 18:37:32 +0900 Subject: [PATCH 17/26] =?UTF-8?q?refactor=20:=20yml=20=ED=8C=8C=EC=9D=BC?= =?UTF-8?q?=20=EA=B5=AC=EC=A1=B0=20=EB=B3=80=EA=B2=BD?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../java/space/space_spring/jwt/JwtLoginProvider.java | 8 ++++---- .../java/space/space_spring/service/OAuthService.java | 1 - src/main/resources/application.yml | 9 +++++---- 3 files changed, 9 insertions(+), 9 deletions(-) diff --git a/src/main/java/space/space_spring/jwt/JwtLoginProvider.java b/src/main/java/space/space_spring/jwt/JwtLoginProvider.java index 748d0e13..e76b7b47 100644 --- a/src/main/java/space/space_spring/jwt/JwtLoginProvider.java +++ b/src/main/java/space/space_spring/jwt/JwtLoginProvider.java @@ -18,16 +18,16 @@ @Slf4j @Component public class JwtLoginProvider { - @Value("${secret.access-secret-key}") + @Value("${secret.jwt.access-secret-key}") private String ACCESS_SECRET_KEY; - @Value("${secret.refresh-secret-key}") + @Value("${secret.jwt.refresh-secret-key}") private String REFRESH_SECRET_KEY; - @Value("${secret.access-expired-in}") + @Value("${secret.jwt.access-expired-in}") private Long ACCESS_EXPIRED_IN; - @Value("${secret.refresh-expired-in}") + @Value("${secret.jwt.refresh-expired-in}") private Long REFRESH_EXPIRED_IN; public String generateToken(User user, TokenType tokenType) { diff --git a/src/main/java/space/space_spring/service/OAuthService.java b/src/main/java/space/space_spring/service/OAuthService.java index ba0fa4fb..bd4d3d46 100644 --- a/src/main/java/space/space_spring/service/OAuthService.java +++ b/src/main/java/space/space_spring/service/OAuthService.java @@ -40,7 +40,6 @@ public class OAuthService { private static final String JWT_TOKEN_PREFIX = "Bearer "; - /** * 카카오 인증 서버가 전달해준 유저의 인가코드로 토큰 발급 요청 */ diff --git a/src/main/resources/application.yml b/src/main/resources/application.yml index 82c93ceb..fd01133e 100644 --- a/src/main/resources/application.yml +++ b/src/main/resources/application.yml @@ -86,10 +86,11 @@ spring: on-profile: "devSecret" secret: - jwt-secret-key: ${JWT_SECRET_KEY} - jwt-login-secret-key: ${JWT_SECRET_KEY_LOGIN} - jwt-user-space-secret-key: ${JWT_SECRET_KEY_USER_SPACE} - jwt-expired-in: ${JWT_EXPIRED_IN:3600000} + jwt: + access-secret-key: ${ACCESS_SECRET_KEY} + refresh-secret-key: ${REFRESH_SECRET_KEY} + access-expired-in: ${ACCESS_EXPIRED_IN} + refresh-expired-in: ${REFRESH_EXPIRED_IN} --- spring: From 373b392301186cef36578f330a31f309d94ba77b Mon Sep 17 00:00:00 2001 From: seongjunnoh Date: Wed, 11 Sep 2024 19:16:09 +0900 Subject: [PATCH 18/26] =?UTF-8?q?refactor=20:=20refresh=20token=20?= =?UTF-8?q?=EC=83=9D=EC=84=B1=EC=8B=9C=20payload=EC=97=90=20userId=20?= =?UTF-8?q?=EA=B0=92=20=EC=A0=9C=EA=B1=B0?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../space_spring/controller/OAuthController.java | 2 -- .../space_spring/controller/UserController.java | 4 ---- .../space/space_spring/jwt/JwtLoginProvider.java | 15 ++++++++++++++- .../space/space_spring/util/user/UserUtils.java | 1 - 4 files changed, 14 insertions(+), 8 deletions(-) diff --git a/src/main/java/space/space_spring/controller/OAuthController.java b/src/main/java/space/space_spring/controller/OAuthController.java index fb389cec..d2e292a3 100644 --- a/src/main/java/space/space_spring/controller/OAuthController.java +++ b/src/main/java/space/space_spring/controller/OAuthController.java @@ -6,11 +6,9 @@ import lombok.RequiredArgsConstructor; import lombok.extern.slf4j.Slf4j; import org.springframework.beans.factory.annotation.Value; -import org.springframework.http.HttpHeaders; import org.springframework.web.bind.annotation.*; import space.space_spring.dto.jwt.TokenDTO; import space.space_spring.dto.oAuth.KakaoInfo; -import space.space_spring.dto.oAuth.OAuthLoginResponse; import space.space_spring.entity.User; import space.space_spring.response.BaseResponse; import space.space_spring.service.OAuthService; diff --git a/src/main/java/space/space_spring/controller/UserController.java b/src/main/java/space/space_spring/controller/UserController.java index de0843d8..99b2b077 100644 --- a/src/main/java/space/space_spring/controller/UserController.java +++ b/src/main/java/space/space_spring/controller/UserController.java @@ -3,14 +3,12 @@ import jakarta.servlet.http.HttpServletResponse; import lombok.RequiredArgsConstructor; import lombok.extern.slf4j.Slf4j; -import org.springframework.context.support.DefaultMessageSourceResolvable; import org.springframework.validation.BindingResult; import org.springframework.validation.annotation.Validated; import org.springframework.web.bind.annotation.*; import space.space_spring.dto.user.GetUserProfileListDto; import space.space_spring.argumentResolver.jwtLogin.JwtLoginAuth; import space.space_spring.dto.user.PostLoginDto; -import space.space_spring.dto.user.request.PostUserLoginRequest; import space.space_spring.dto.user.request.PostUserSignupRequest; import space.space_spring.dto.user.response.GetSpaceInfoForUserResponse; import space.space_spring.exception.CustomException; @@ -18,8 +16,6 @@ import space.space_spring.service.UserService; import space.space_spring.util.userSpace.UserSpaceUtils; -import java.util.stream.Collectors; - import static space.space_spring.response.status.BaseExceptionResponseStatus.*; import static space.space_spring.util.bindingResult.BindingResultUtils.getErrorMessage; diff --git a/src/main/java/space/space_spring/jwt/JwtLoginProvider.java b/src/main/java/space/space_spring/jwt/JwtLoginProvider.java index e76b7b47..44a6355f 100644 --- a/src/main/java/space/space_spring/jwt/JwtLoginProvider.java +++ b/src/main/java/space/space_spring/jwt/JwtLoginProvider.java @@ -38,11 +38,24 @@ public String generateToken(User user, TokenType tokenType) { Long userId = user.getUserId(); + return makeToken(tokenType, userId, now, expiration); + } + + private String makeToken(TokenType tokenType, Long userId, Date now, Date expiration) { + if (tokenType.equals(TokenType.ACCESS)) { + return Jwts.builder() +// .setClaims(claims) + .setIssuedAt(now) + .setExpiration(expiration) + .claim("userId", userId) + .signWith(SignatureAlgorithm.HS256, choiceSecretKey(tokenType)) + .compact(); + } + return Jwts.builder() // .setClaims(claims) .setIssuedAt(now) .setExpiration(expiration) - .claim("userId", userId) .signWith(SignatureAlgorithm.HS256, choiceSecretKey(tokenType)) .compact(); } diff --git a/src/main/java/space/space_spring/util/user/UserUtils.java b/src/main/java/space/space_spring/util/user/UserUtils.java index d85798c7..e4333292 100644 --- a/src/main/java/space/space_spring/util/user/UserUtils.java +++ b/src/main/java/space/space_spring/util/user/UserUtils.java @@ -10,7 +10,6 @@ import java.util.UUID; -import static space.space_spring.entity.enumStatus.UserSignupType.LOCAL; import static space.space_spring.response.status.BaseExceptionResponseStatus.*; @Component From 84de52a50e16fffa35be78fd48ff50d4caab3da3 Mon Sep 17 00:00:00 2001 From: seongjunnoh Date: Wed, 11 Sep 2024 19:51:08 +0900 Subject: [PATCH 19/26] =?UTF-8?q?refactor=20:=20TokenStorage=20=EC=97=94?= =?UTF-8?q?=ED=8B=B0=ED=8B=B0=20=EC=83=9D=EC=84=B1=20&=20refresh=20token?= =?UTF-8?q?=20=EC=A0=80=EC=9E=A5=EC=9D=84=20=ED=95=B4=EB=8B=B9=20=EC=97=94?= =?UTF-8?q?=ED=8B=B0=ED=8B=B0=EC=97=90=EA=B2=8C=20=EC=9C=84=EC=9E=84?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../space/space_spring/dao/JwtRepository.java | 12 +++++++ .../space_spring/dto/user/PostLoginDto.java | 6 ++-- .../space_spring/entity/TokenStorage.java | 32 +++++++++++++++++++ .../java/space/space_spring/entity/User.java | 11 ------- .../space_spring/service/OAuthService.java | 14 ++++++-- .../space_spring/service/UserService.java | 27 +++++++++++----- 6 files changed, 77 insertions(+), 25 deletions(-) create mode 100644 src/main/java/space/space_spring/dao/JwtRepository.java create mode 100644 src/main/java/space/space_spring/entity/TokenStorage.java diff --git a/src/main/java/space/space_spring/dao/JwtRepository.java b/src/main/java/space/space_spring/dao/JwtRepository.java new file mode 100644 index 00000000..7e424b81 --- /dev/null +++ b/src/main/java/space/space_spring/dao/JwtRepository.java @@ -0,0 +1,12 @@ +package space.space_spring.dao; + +import org.springframework.data.jpa.repository.JpaRepository; +import org.springframework.stereotype.Repository; +import space.space_spring.entity.TokenStorage; +import space.space_spring.entity.User; + +@Repository +public interface JwtRepository extends JpaRepository { + + TokenStorage findByUser(User user); +} diff --git a/src/main/java/space/space_spring/dto/user/PostLoginDto.java b/src/main/java/space/space_spring/dto/user/PostLoginDto.java index 5202d58f..94643c3f 100644 --- a/src/main/java/space/space_spring/dto/user/PostLoginDto.java +++ b/src/main/java/space/space_spring/dto/user/PostLoginDto.java @@ -2,15 +2,13 @@ import jakarta.validation.constraints.NotBlank; import jakarta.validation.constraints.Pattern; -import lombok.AllArgsConstructor; -import lombok.Getter; -import lombok.NoArgsConstructor; -import lombok.Setter; +import lombok.*; import space.space_spring.dto.jwt.TokenDTO; @Getter @NoArgsConstructor @AllArgsConstructor +@Builder public class PostLoginDto { private TokenDTO tokenDTO; diff --git a/src/main/java/space/space_spring/entity/TokenStorage.java b/src/main/java/space/space_spring/entity/TokenStorage.java new file mode 100644 index 00000000..38104958 --- /dev/null +++ b/src/main/java/space/space_spring/entity/TokenStorage.java @@ -0,0 +1,32 @@ +package space.space_spring.entity; + +import jakarta.persistence.*; +import lombok.AllArgsConstructor; +import lombok.Builder; +import lombok.Getter; +import lombok.NoArgsConstructor; + +@Entity +@Table(name = "Token_Storage") +@Getter +@Builder +@NoArgsConstructor +@AllArgsConstructor +public class TokenStorage { + + @Id @GeneratedValue + @Column(name = "token_storage_id") + private Long tokenStorageId; + + @OneToOne + @Column(name = "user_id") + private User user; + + @Column(name = "token_value") + private String tokenValue; + + public void updateTokenValue(String tokenValue) { + this.tokenValue = tokenValue; + } + +} diff --git a/src/main/java/space/space_spring/entity/User.java b/src/main/java/space/space_spring/entity/User.java index 255f7d0b..120ed335 100644 --- a/src/main/java/space/space_spring/entity/User.java +++ b/src/main/java/space/space_spring/entity/User.java @@ -26,17 +26,6 @@ public class User extends BaseEntity { @Column(name = "signup_type") private String signupType; // 유저가 회원가입을 진행한 방식 (local, kakao, naver, google 등등) - @Column(name = "refresh_token") - private String refreshToken; - - public void updateRefreshToken(String refreshToken) { - this.refreshToken = refreshToken; - } - - public void destroyRefreshToken() { - this.refreshToken = null; - } - public void saveUser(String email, String password, String userName, UserSignupType signupType) { this.email = email; this.password = password; diff --git a/src/main/java/space/space_spring/service/OAuthService.java b/src/main/java/space/space_spring/service/OAuthService.java index bd4d3d46..93642099 100644 --- a/src/main/java/space/space_spring/service/OAuthService.java +++ b/src/main/java/space/space_spring/service/OAuthService.java @@ -14,10 +14,12 @@ import org.springframework.util.LinkedMultiValueMap; import org.springframework.util.MultiValueMap; import org.springframework.web.client.RestTemplate; +import space.space_spring.dao.JwtRepository; import space.space_spring.dao.UserDao; import space.space_spring.dto.jwt.TokenDTO; import space.space_spring.dto.jwt.TokenType; import space.space_spring.dto.oAuth.KakaoInfo; +import space.space_spring.entity.TokenStorage; import space.space_spring.entity.User; import space.space_spring.exception.jwt.bad_request.JwtNoTokenException; import space.space_spring.exception.jwt.bad_request.JwtUnsupportedTokenException; @@ -37,6 +39,7 @@ public class OAuthService { private final UserUtils userUtils; private final JwtLoginProvider jwtLoginProvider; private final UserDao userDao; + private final JwtRepository jwtRepository; private static final String JWT_TOKEN_PREFIX = "Bearer "; @@ -120,12 +123,19 @@ public TokenDTO provideJwtToOAuthUser(User userByOAuthInfo) { String accessToken = jwtLoginProvider.generateToken(userByOAuthInfo, TokenType.ACCESS); String refreshToken = jwtLoginProvider.generateToken(userByOAuthInfo, TokenType.REFRESH); - return new TokenDTO(accessToken, refreshToken); + return TokenDTO.builder() + .accessToken(accessToken) + .refreshToken(refreshToken) + .build(); } @Transactional public void updateRefreshToken(User user, String refreshToken) { - user.updateRefreshToken(refreshToken); + // TODO 1. TokenStorage entity find + TokenStorage tokenStorage = jwtRepository.findByUser(user); + + // TODO 2. tokenValue 값을 새로 발급한 refresh token으로 update + tokenStorage.updateTokenValue(refreshToken); } public String resolveRefreshToken(HttpServletRequest request) { diff --git a/src/main/java/space/space_spring/service/UserService.java b/src/main/java/space/space_spring/service/UserService.java index 836c3a28..9186598c 100644 --- a/src/main/java/space/space_spring/service/UserService.java +++ b/src/main/java/space/space_spring/service/UserService.java @@ -4,15 +4,16 @@ import lombok.extern.slf4j.Slf4j; import org.springframework.stereotype.Service; import org.springframework.transaction.annotation.Transactional; +import space.space_spring.dao.JwtRepository; import space.space_spring.dao.UserSpaceDao; import space.space_spring.dto.jwt.TokenDTO; import space.space_spring.dto.jwt.TokenType; import space.space_spring.dto.user.GetUserProfileListDto; import space.space_spring.dto.user.PostLoginDto; import space.space_spring.dto.user.dto.SpaceChoiceViewDto; -import space.space_spring.dto.user.request.PostUserLoginRequest; import space.space_spring.dto.user.request.PostUserSignupRequest; import space.space_spring.dto.user.response.GetSpaceInfoForUserResponse; +import space.space_spring.entity.TokenStorage; import space.space_spring.entity.UserSpace; import space.space_spring.entity.enumStatus.UserSignupType; import space.space_spring.exception.CustomException; @@ -23,7 +24,6 @@ import java.util.ArrayList; import java.util.List; -import java.util.Optional; import static space.space_spring.entity.enumStatus.UserSignupType.LOCAL; import static space.space_spring.response.status.BaseExceptionResponseStatus.*; @@ -37,6 +37,7 @@ public class UserService { private final JwtLoginProvider jwtLoginProvider; private final UserSpaceDao userSpaceDao; private final UserUtils userUtils; + private final JwtRepository jwtRepository; @Transactional public Long signup(PostUserSignupRequest postUserSignupRequest) { @@ -75,12 +76,22 @@ public PostLoginDto login(PostLoginDto.Request request) { String refreshToken = jwtLoginProvider.generateToken(userByEmail, TokenType.REFRESH); // TODO 4. refresh token db에 저장 - userByEmail.updateRefreshToken(refreshToken); - - return new PostLoginDto( - new TokenDTO(refreshToken, accessToken), - userByEmail.getUserId() - ); + TokenStorage tokenStorage = TokenStorage.builder() + .user(userByEmail) + .tokenValue(refreshToken) + .build(); + jwtRepository.save(tokenStorage); + + // TODO 5. return + TokenDTO tokenDTO = TokenDTO.builder() + .refreshToken(refreshToken) + .accessToken(accessToken) + .build(); + + return PostLoginDto.builder() + .tokenDTO(tokenDTO) + .userId(userByEmail.getUserId()) + .build(); } private void validatePassword(User userByEmail, String password) { From 5af770244c98e8939188e5b9c30e24dbda2ad959 Mon Sep 17 00:00:00 2001 From: seongjunnoh Date: Sun, 22 Sep 2024 17:33:08 +0900 Subject: [PATCH 20/26] =?UTF-8?q?refactor=20:=20access=20token=20=EA=B0=B1?= =?UTF-8?q?=EC=8B=A0=20api=20=EC=88=98=EC=A0=95?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../controller/OAuthController.java | 19 +++-- .../space/space_spring/dao/JwtRepository.java | 5 +- .../space_spring/dao/UserRepository.java | 15 ++++ .../space_spring/entity/TokenStorage.java | 6 +- .../status/BaseExceptionResponseStatus.java | 2 +- .../space_spring/service/OAuthService.java | 75 +++++++++++++------ 6 files changed, 89 insertions(+), 33 deletions(-) create mode 100644 src/main/java/space/space_spring/dao/UserRepository.java diff --git a/src/main/java/space/space_spring/controller/OAuthController.java b/src/main/java/space/space_spring/controller/OAuthController.java index d2e292a3..ba78ca9d 100644 --- a/src/main/java/space/space_spring/controller/OAuthController.java +++ b/src/main/java/space/space_spring/controller/OAuthController.java @@ -94,21 +94,24 @@ public void kakaoCallback(@RequestParam(name = "code") String code, HttpServletR */ @PostMapping("/new-token") public BaseResponse updateAccessToken(HttpServletRequest request, HttpServletResponse response) throws IOException { - // refresh token 파싱 - String refreshToken = oAuthService.resolveRefreshToken(request); + // access token, refresh token 파싱 + TokenDTO tokenDTO = oAuthService.resolveTokenPair(request); + + // access token 로부터 user find + User userByAccessToken = oAuthService.getUserByAccessToken(tokenDTO.getAccessToken()); // refresh token 유효성 검사 - oAuthService.validateRefreshToken(refreshToken); + oAuthService.validateRefreshToken(userByAccessToken, tokenDTO.getRefreshToken()); // access token, refresh token 새로 발급 - TokenDTO tokenDTO = oAuthService.updateTokenPair(refreshToken); + TokenDTO newTokenDTO = oAuthService.updateTokenPair(userByAccessToken); // response header에 새로 발급한 token pair set - response.setHeader("Authorization-refresh", "Bearer " + tokenDTO.getRefreshToken()); - response.setHeader("Authorization", "Bearer " + tokenDTO.getAccessToken()); + response.setHeader("Authorization-refresh", "Bearer " + newTokenDTO.getRefreshToken()); + response.setHeader("Authorization", "Bearer " + newTokenDTO.getAccessToken()); - System.out.println("tokenDTO.getAccessToken() = " + tokenDTO.getAccessToken()); - System.out.println("tokenDTO.getRefreshToken() = " + tokenDTO.getRefreshToken()); + System.out.println("tokenDTO.getAccessToken() = " + newTokenDTO.getAccessToken()); + System.out.println("tokenDTO.getRefreshToken() = " + newTokenDTO.getRefreshToken()); // return return new BaseResponse<>("토큰 갱신 요청 성공"); diff --git a/src/main/java/space/space_spring/dao/JwtRepository.java b/src/main/java/space/space_spring/dao/JwtRepository.java index 7e424b81..e336dd4e 100644 --- a/src/main/java/space/space_spring/dao/JwtRepository.java +++ b/src/main/java/space/space_spring/dao/JwtRepository.java @@ -5,8 +5,11 @@ import space.space_spring.entity.TokenStorage; import space.space_spring.entity.User; +import java.util.Optional; + @Repository public interface JwtRepository extends JpaRepository { - TokenStorage findByUser(User user); + Optional findByUser(User user); + void deleteByUser(User user); } diff --git a/src/main/java/space/space_spring/dao/UserRepository.java b/src/main/java/space/space_spring/dao/UserRepository.java new file mode 100644 index 00000000..b4245e48 --- /dev/null +++ b/src/main/java/space/space_spring/dao/UserRepository.java @@ -0,0 +1,15 @@ +package space.space_spring.dao; + +import org.springframework.data.jpa.repository.JpaRepository; +import org.springframework.data.jpa.repository.Query; +import org.springframework.stereotype.Repository; +import space.space_spring.entity.User; + +import java.util.Optional; + +@Repository +public interface UserRepository extends JpaRepository { + + @Query("SELECT u FROM User u WHERE u.userId = :userId AND u.status = 'ACTIVE'") + Optional findByUserId(Long userId); +} diff --git a/src/main/java/space/space_spring/entity/TokenStorage.java b/src/main/java/space/space_spring/entity/TokenStorage.java index 38104958..5519d8e2 100644 --- a/src/main/java/space/space_spring/entity/TokenStorage.java +++ b/src/main/java/space/space_spring/entity/TokenStorage.java @@ -19,7 +19,7 @@ public class TokenStorage { private Long tokenStorageId; @OneToOne - @Column(name = "user_id") +// @Column(name = "user_id") private User user; @Column(name = "token_value") @@ -29,4 +29,8 @@ public void updateTokenValue(String tokenValue) { this.tokenValue = tokenValue; } + public boolean checkTokenValue(String tokenValue) { + return this.tokenValue.equals(tokenValue); + } + } diff --git a/src/main/java/space/space_spring/response/status/BaseExceptionResponseStatus.java b/src/main/java/space/space_spring/response/status/BaseExceptionResponseStatus.java index b572d313..eef91e92 100644 --- a/src/main/java/space/space_spring/response/status/BaseExceptionResponseStatus.java +++ b/src/main/java/space/space_spring/response/status/BaseExceptionResponseStatus.java @@ -39,7 +39,7 @@ public enum BaseExceptionResponseStatus implements ResponseStatus { INVALID_TOKEN(4003, HttpStatus.UNAUTHORIZED, "유효하지 않은 토큰입니다."), MALFORMED_TOKEN(4004, HttpStatus.UNAUTHORIZED, "토큰이 올바르게 구성되지 않았습니다."), EXPIRED_ACCESS_TOKEN(4005, HttpStatus.UNAUTHORIZED, "만료된 access token 입니다."), - TOKEN_MISMATCH(4006, HttpStatus.UNAUTHORIZED, "로그인 정보가 토큰 정보와 일치하지 않습니다."), + TOKEN_MISMATCH(4006, HttpStatus.UNAUTHORIZED, "저장된 refresh token 과 전달받은 refresh token 이 일치하지 않습니다. 다시 로그인해야합니다."), CANNOT_FIND_USER_ID(4007, HttpStatus.UNAUTHORIZED,"토큰의 userId정보를 찾을 수 없습니다."), WRONG_SIGNATURE_JWT(4008,HttpStatus.UNAUTHORIZED,"JWT 서명이 잘못 되었습니다."), EXPIRED_REFRESH_TOKEN(4009, HttpStatus.UNAUTHORIZED, "만료된 refresh token 입니다. 다시 로그인해야합니다."), diff --git a/src/main/java/space/space_spring/service/OAuthService.java b/src/main/java/space/space_spring/service/OAuthService.java index 93642099..fad9cbe9 100644 --- a/src/main/java/space/space_spring/service/OAuthService.java +++ b/src/main/java/space/space_spring/service/OAuthService.java @@ -16,15 +16,17 @@ import org.springframework.web.client.RestTemplate; import space.space_spring.dao.JwtRepository; import space.space_spring.dao.UserDao; +import space.space_spring.dao.UserRepository; import space.space_spring.dto.jwt.TokenDTO; import space.space_spring.dto.jwt.TokenType; import space.space_spring.dto.oAuth.KakaoInfo; import space.space_spring.entity.TokenStorage; import space.space_spring.entity.User; +import space.space_spring.exception.CustomException; import space.space_spring.exception.jwt.bad_request.JwtNoTokenException; import space.space_spring.exception.jwt.bad_request.JwtUnsupportedTokenException; import space.space_spring.exception.jwt.unauthorized.JwtExpiredTokenException; -import space.space_spring.exception.jwt.unauthorized.JwtInvalidTokenException; +import space.space_spring.exception.jwt.unauthorized.JwtUnauthorizedTokenException; import space.space_spring.jwt.JwtLoginProvider; import space.space_spring.util.user.UserUtils; @@ -40,6 +42,7 @@ public class OAuthService { private final JwtLoginProvider jwtLoginProvider; private final UserDao userDao; private final JwtRepository jwtRepository; + private final UserRepository userRepository; private static final String JWT_TOKEN_PREFIX = "Bearer "; @@ -131,18 +134,26 @@ public TokenDTO provideJwtToOAuthUser(User userByOAuthInfo) { @Transactional public void updateRefreshToken(User user, String refreshToken) { - // TODO 1. TokenStorage entity find - TokenStorage tokenStorage = jwtRepository.findByUser(user); + TokenStorage tokenStorage = jwtRepository.findByUser(user) + .orElseThrow(() -> new JwtUnauthorizedTokenException(TOKEN_MISMATCH)); - // TODO 2. tokenValue 값을 새로 발급한 refresh token으로 update tokenStorage.updateTokenValue(refreshToken); } - public String resolveRefreshToken(HttpServletRequest request) { - String token = request.getHeader("Authorization-refresh"); - validateToken(token); - return token.substring(JWT_TOKEN_PREFIX.length()); + public TokenDTO resolveTokenPair(HttpServletRequest request) { + // TODO 1. access token 파싱 + String accessToken = request.getHeader(HttpHeaders.AUTHORIZATION); + validateToken(accessToken); + // TODO 2. refresh token 파싱 + String refreshToken = request.getHeader("Authorization-refresh"); + validateToken(refreshToken); + + // TODO 3. return + return TokenDTO.builder() + .accessToken(accessToken.substring(JWT_TOKEN_PREFIX.length())) + .refreshToken(refreshToken.substring(JWT_TOKEN_PREFIX.length())) + .build(); } private void validateToken(String token) { @@ -155,35 +166,55 @@ private void validateToken(String token) { } @Transactional - public void validateRefreshToken(String refreshToken) { + public void validateRefreshToken(User user, String refreshToken) { + TokenStorage tokenStorage = jwtRepository.findByUser(user) + .orElseThrow(() -> + { + // db에서 row delete 하는 코드 추가 + jwtRepository.deleteByUser(user); + throw new JwtUnauthorizedTokenException(TOKEN_MISMATCH); + }); + // TODO 1. refresh token의 만료시간 체크 if (jwtLoginProvider.isExpiredToken(refreshToken, TokenType.REFRESH)) { // refresh token이 만료된 경우 -> 예외 발생 -> 유저의 재 로그인 유도 + // db에서 row delete 하는 코드 추가 + jwtRepository.deleteByUser(user); throw new JwtExpiredTokenException(EXPIRED_REFRESH_TOKEN); } // TODO 2. refresh token이 db에 실제로 존재하는지 체크 - if (userDao.findUserByRefreshToken(refreshToken).isEmpty()) { + if (!tokenStorage.checkTokenValue(refreshToken)) { // refresh token이 db에 존재하지 않느 경우 -> 유효하지 않은 refresh token이므로 예외 발생 - throw new JwtInvalidTokenException(INVALID_TOKEN); + // db에서 row delete 하는 코드 추가 + jwtRepository.deleteByUser(user); + throw new JwtUnauthorizedTokenException(TOKEN_MISMATCH); } } @Transactional - public TokenDTO updateTokenPair(String refreshToken) { - // TODO 1. refresh token으로 user find - Long userIdFromToken = jwtLoginProvider.getUserIdFromToken(refreshToken, TokenType.REFRESH); - User userByUserId = userUtils.findUserByUserId(userIdFromToken); + public TokenDTO updateTokenPair(User user) { + // TODO 1. new access token, refresh token 발급 + String newAccessToken = jwtLoginProvider.generateToken(user, TokenType.ACCESS); + String newRefreshToken = jwtLoginProvider.generateToken(user, TokenType.REFRESH); - // TODO 2. new access token, refresh token 발급 - String newAccessToken = jwtLoginProvider.generateToken(userByUserId, TokenType.ACCESS); - String newRefreshToken = jwtLoginProvider.generateToken(userByUserId, TokenType.REFRESH); + // TODO 2. db의 refresh token update + TokenStorage tokenStorage = jwtRepository.findByUser(user) + .orElseThrow(() -> new JwtUnauthorizedTokenException(TOKEN_MISMATCH)); - // TODO 3. db의 refresh token update - userByUserId.updateRefreshToken(newRefreshToken); + tokenStorage.updateTokenValue(newRefreshToken); - // TODO 4. return - return new TokenDTO(newRefreshToken, newAccessToken); + // TODO 3. return + return TokenDTO.builder() + .accessToken(newAccessToken) + .refreshToken(newRefreshToken) + .build(); } + public User getUserByAccessToken(String accessToken) { + Long userIdFromToken = jwtLoginProvider.getUserIdFromToken(accessToken, TokenType.ACCESS); + + return userRepository.findByUserId(userIdFromToken) + .orElseThrow(() -> new CustomException(USER_NOT_FOUND)); + } } From 2c0bf76320533febc93cb30ac985c124e4dd2867 Mon Sep 17 00:00:00 2001 From: seongjunnoh Date: Sun, 22 Sep 2024 17:34:14 +0900 Subject: [PATCH 21/26] =?UTF-8?q?fix=20:=20BeanCreationException=20?= =?UTF-8?q?=ED=95=B4=EA=B2=B0=EC=9D=84=20=EC=9C=84=ED=95=B4=20ByteBuddy=20?= =?UTF-8?q?=EC=9D=98=EC=A1=B4=EC=84=B1=20=EC=B6=94=EA=B0=80?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- build.gradle | 1 + 1 file changed, 1 insertion(+) diff --git a/build.gradle b/build.gradle index ac20d2f1..33c1d233 100644 --- a/build.gradle +++ b/build.gradle @@ -40,6 +40,7 @@ dependencies { implementation 'org.springframework.boot:spring-boot-starter-security' implementation 'org.springframework.boot:spring-boot-starter-websocket' // webSocket 추가 implementation 'org.springframework.boot:spring-boot-starter-data-mongodb' // MongoDB 추가 + implementation 'net.bytebuddy:byte-buddy:1.14.5' // QueryDSL implementation 'com.querydsl:querydsl-jpa:5.0.0:jakarta' From 8f4ae5c452a0c17840c48b9f434215b97d976130 Mon Sep 17 00:00:00 2001 From: seongjunnoh Date: Sun, 22 Sep 2024 17:52:55 +0900 Subject: [PATCH 22/26] =?UTF-8?q?fix=20:=20=EB=A7=8C=EB=A3=8C=EB=90=9C=20a?= =?UTF-8?q?ccess=20token=20=EC=9C=BC=EB=A1=9C=EB=B6=80=ED=84=B0=20userId?= =?UTF-8?q?=20get=20=ED=95=A0=20=EB=95=8C=20exception=20=EB=B0=9C=EC=83=9D?= =?UTF-8?q?=ED=95=98=EB=8A=94=20=EC=97=90=EB=9F=AC=20=ED=95=B4=EA=B2=B0?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/main/java/space/space_spring/jwt/JwtLoginProvider.java | 3 +++ 1 file changed, 3 insertions(+) diff --git a/src/main/java/space/space_spring/jwt/JwtLoginProvider.java b/src/main/java/space/space_spring/jwt/JwtLoginProvider.java index 44a6355f..31242bb8 100644 --- a/src/main/java/space/space_spring/jwt/JwtLoginProvider.java +++ b/src/main/java/space/space_spring/jwt/JwtLoginProvider.java @@ -108,6 +108,9 @@ public Long getUserIdFromToken(String token, TokenType tokenType) { .setSigningKey(choiceSecretKey(tokenType)).build() .parseClaimsJws(token); return claims.getBody().get("userId", Long.class); + } catch (ExpiredJwtException e) { + // 만료된 토큰에서 userId 추출 + return e.getClaims().get("userId", Long.class); } catch (JwtException e) { log.error("[JwtTokenProvider.getJwtPayloadDtoFromToken]", e); throw e; From 432d54ff85d65f6e7a1b0f1b793c6a3ff110a534 Mon Sep 17 00:00:00 2001 From: seongjunnoh Date: Sun, 22 Sep 2024 20:21:53 +0900 Subject: [PATCH 23/26] =?UTF-8?q?refactor=20:=20build.gradle=20=EC=97=90?= =?UTF-8?q?=20=EC=B6=94=EA=B0=80=ED=95=9C=20buddy=20=20=EC=9D=98=EC=A1=B4?= =?UTF-8?q?=EC=84=B1=20=EC=A0=9C=EA=B1=B0?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- build.gradle | 1 - 1 file changed, 1 deletion(-) diff --git a/build.gradle b/build.gradle index 33c1d233..ac20d2f1 100644 --- a/build.gradle +++ b/build.gradle @@ -40,7 +40,6 @@ dependencies { implementation 'org.springframework.boot:spring-boot-starter-security' implementation 'org.springframework.boot:spring-boot-starter-websocket' // webSocket 추가 implementation 'org.springframework.boot:spring-boot-starter-data-mongodb' // MongoDB 추가 - implementation 'net.bytebuddy:byte-buddy:1.14.5' // QueryDSL implementation 'com.querydsl:querydsl-jpa:5.0.0:jakarta' From 89a444cd10a60b50df47aa0637829081e1e6ed57 Mon Sep 17 00:00:00 2001 From: seongjunnoh Date: Mon, 23 Sep 2024 17:12:10 +0900 Subject: [PATCH 24/26] =?UTF-8?q?refactor=20:=20TokenDTO=20->=20TokenPairD?= =?UTF-8?q?TO=20DTO=20=EC=9D=B4=EB=A6=84=20=EB=B3=80=EA=B2=BD?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../controller/OAuthController.java | 30 +++++++++---------- .../controller/UserController.java | 8 ++--- .../jwt/{TokenDTO.java => TokenPairDTO.java} | 2 +- .../space_spring/dto/user/PostLoginDto.java | 4 +-- .../space_spring/service/OAuthService.java | 14 ++++----- .../space_spring/service/UserService.java | 6 ++-- 6 files changed, 32 insertions(+), 32 deletions(-) rename src/main/java/space/space_spring/dto/jwt/{TokenDTO.java => TokenPairDTO.java} (90%) diff --git a/src/main/java/space/space_spring/controller/OAuthController.java b/src/main/java/space/space_spring/controller/OAuthController.java index ba78ca9d..dc1b7fa1 100644 --- a/src/main/java/space/space_spring/controller/OAuthController.java +++ b/src/main/java/space/space_spring/controller/OAuthController.java @@ -7,7 +7,7 @@ import lombok.extern.slf4j.Slf4j; import org.springframework.beans.factory.annotation.Value; import org.springframework.web.bind.annotation.*; -import space.space_spring.dto.jwt.TokenDTO; +import space.space_spring.dto.jwt.TokenPairDTO; import space.space_spring.dto.oAuth.KakaoInfo; import space.space_spring.entity.User; import space.space_spring.response.BaseResponse; @@ -67,21 +67,21 @@ public void kakaoCallback(@RequestParam(name = "code") String code, HttpServletR User userByOAuthInfo = oAuthService.findUserByOAuthInfo(kakaoInfo); // TODO 5. 카카오 로그인 유저에게 jwt 발급 - TokenDTO tokenDTO = oAuthService.provideJwtToOAuthUser(userByOAuthInfo); + TokenPairDTO tokenPairDTO = oAuthService.provideJwtToOAuthUser(userByOAuthInfo); // TODO 6. 카카오 로그인 유저에게 발급한 refresh token을 db에 저장 - oAuthService.updateRefreshToken(userByOAuthInfo, tokenDTO.getRefreshToken()); + oAuthService.updateRefreshToken(userByOAuthInfo, tokenPairDTO.getRefreshToken()); - System.out.println("tokenDTO.getAccessToken() = " + tokenDTO.getAccessToken()); - System.out.println("tokenDTO.getRefreshToken() = " + tokenDTO.getRefreshToken()); + System.out.println("tokenPairDTO.getAccessToken() = " + tokenPairDTO.getAccessToken()); + System.out.println("tokenPairDTO.getRefreshToken() = " + tokenPairDTO.getRefreshToken()); // 클라이언트로 response 전달 // -> 메서드 분리 ?? // 공백문자가 %20 으로 전달되는 듯 함 -> 프론트 분들과 협의 필요할 듯 String redirectUrl = String.format( "https://kuit-space.github.io/KUIT-Space-front/login?access-token=%s&refresh-token=%s&userId=%s", - "Bearer " + tokenDTO.getAccessToken(), - "Bearer " + tokenDTO.getRefreshToken(), + "Bearer " + tokenPairDTO.getAccessToken(), + "Bearer " + tokenPairDTO.getRefreshToken(), userByOAuthInfo.getUserId() ); @@ -95,23 +95,23 @@ public void kakaoCallback(@RequestParam(name = "code") String code, HttpServletR @PostMapping("/new-token") public BaseResponse updateAccessToken(HttpServletRequest request, HttpServletResponse response) throws IOException { // access token, refresh token 파싱 - TokenDTO tokenDTO = oAuthService.resolveTokenPair(request); + TokenPairDTO tokenPairDTO = oAuthService.resolveTokenPair(request); // access token 로부터 user find - User userByAccessToken = oAuthService.getUserByAccessToken(tokenDTO.getAccessToken()); + User userByAccessToken = oAuthService.getUserByAccessToken(tokenPairDTO.getAccessToken()); // refresh token 유효성 검사 - oAuthService.validateRefreshToken(userByAccessToken, tokenDTO.getRefreshToken()); + oAuthService.validateRefreshToken(userByAccessToken, tokenPairDTO.getRefreshToken()); // access token, refresh token 새로 발급 - TokenDTO newTokenDTO = oAuthService.updateTokenPair(userByAccessToken); + TokenPairDTO newTokenPairDTO = oAuthService.updateTokenPair(userByAccessToken); // response header에 새로 발급한 token pair set - response.setHeader("Authorization-refresh", "Bearer " + newTokenDTO.getRefreshToken()); - response.setHeader("Authorization", "Bearer " + newTokenDTO.getAccessToken()); + response.setHeader("Authorization-refresh", "Bearer " + newTokenPairDTO.getRefreshToken()); + response.setHeader("Authorization", "Bearer " + newTokenPairDTO.getAccessToken()); - System.out.println("tokenDTO.getAccessToken() = " + newTokenDTO.getAccessToken()); - System.out.println("tokenDTO.getRefreshToken() = " + newTokenDTO.getRefreshToken()); + System.out.println("tokenPairDTO.getAccessToken() = " + newTokenPairDTO.getAccessToken()); + System.out.println("tokenPairDTO.getRefreshToken() = " + newTokenPairDTO.getRefreshToken()); // return return new BaseResponse<>("토큰 갱신 요청 성공"); diff --git a/src/main/java/space/space_spring/controller/UserController.java b/src/main/java/space/space_spring/controller/UserController.java index 99b2b077..aa0ad77c 100644 --- a/src/main/java/space/space_spring/controller/UserController.java +++ b/src/main/java/space/space_spring/controller/UserController.java @@ -53,11 +53,11 @@ public BaseResponse login(@Validated @RequestBody PostLog PostLoginDto login = userService.login(request); - System.out.println("login.getTokenDTO().getRefreshToken() = " + login.getTokenDTO().getRefreshToken()); - System.out.println("login.getTokenDTO().getAccessToken() = " + login.getTokenDTO().getAccessToken()); + System.out.println("login.getTokenPairDTO().getRefreshToken() = " + login.getTokenPairDTO().getRefreshToken()); + System.out.println("login.getTokenPairDTO().getAccessToken() = " + login.getTokenPairDTO().getAccessToken()); - response.setHeader("Authorization-refresh", "Bearer " + login.getTokenDTO().getRefreshToken()); - response.setHeader("Authorization", "Bearer " + login.getTokenDTO().getAccessToken()); + response.setHeader("Authorization-refresh", "Bearer " + login.getTokenPairDTO().getRefreshToken()); + response.setHeader("Authorization", "Bearer " + login.getTokenPairDTO().getAccessToken()); return new BaseResponse<>(new PostLoginDto.Response(login.getUserId())); } diff --git a/src/main/java/space/space_spring/dto/jwt/TokenDTO.java b/src/main/java/space/space_spring/dto/jwt/TokenPairDTO.java similarity index 90% rename from src/main/java/space/space_spring/dto/jwt/TokenDTO.java rename to src/main/java/space/space_spring/dto/jwt/TokenPairDTO.java index 9dca7de7..c2dfdc64 100644 --- a/src/main/java/space/space_spring/dto/jwt/TokenDTO.java +++ b/src/main/java/space/space_spring/dto/jwt/TokenPairDTO.java @@ -9,7 +9,7 @@ @NoArgsConstructor @AllArgsConstructor @Builder -public class TokenDTO { +public class TokenPairDTO { private String refreshToken; private String accessToken; diff --git a/src/main/java/space/space_spring/dto/user/PostLoginDto.java b/src/main/java/space/space_spring/dto/user/PostLoginDto.java index 94643c3f..70327257 100644 --- a/src/main/java/space/space_spring/dto/user/PostLoginDto.java +++ b/src/main/java/space/space_spring/dto/user/PostLoginDto.java @@ -3,7 +3,7 @@ import jakarta.validation.constraints.NotBlank; import jakarta.validation.constraints.Pattern; import lombok.*; -import space.space_spring.dto.jwt.TokenDTO; +import space.space_spring.dto.jwt.TokenPairDTO; @Getter @NoArgsConstructor @@ -11,7 +11,7 @@ @Builder public class PostLoginDto { - private TokenDTO tokenDTO; + private TokenPairDTO TokenPairDTO; private Long userId; @Getter diff --git a/src/main/java/space/space_spring/service/OAuthService.java b/src/main/java/space/space_spring/service/OAuthService.java index fad9cbe9..47165291 100644 --- a/src/main/java/space/space_spring/service/OAuthService.java +++ b/src/main/java/space/space_spring/service/OAuthService.java @@ -17,7 +17,7 @@ import space.space_spring.dao.JwtRepository; import space.space_spring.dao.UserDao; import space.space_spring.dao.UserRepository; -import space.space_spring.dto.jwt.TokenDTO; +import space.space_spring.dto.jwt.TokenPairDTO; import space.space_spring.dto.jwt.TokenType; import space.space_spring.dto.oAuth.KakaoInfo; import space.space_spring.entity.TokenStorage; @@ -122,11 +122,11 @@ public User findUserByOAuthInfo(KakaoInfo kakaoInfo) { return userUtils.findOrCreateUserForOAuthInfo(email, nickname, KAKAO); } - public TokenDTO provideJwtToOAuthUser(User userByOAuthInfo) { + public TokenPairDTO provideJwtToOAuthUser(User userByOAuthInfo) { String accessToken = jwtLoginProvider.generateToken(userByOAuthInfo, TokenType.ACCESS); String refreshToken = jwtLoginProvider.generateToken(userByOAuthInfo, TokenType.REFRESH); - return TokenDTO.builder() + return TokenPairDTO.builder() .accessToken(accessToken) .refreshToken(refreshToken) .build(); @@ -140,7 +140,7 @@ public void updateRefreshToken(User user, String refreshToken) { tokenStorage.updateTokenValue(refreshToken); } - public TokenDTO resolveTokenPair(HttpServletRequest request) { + public TokenPairDTO resolveTokenPair(HttpServletRequest request) { // TODO 1. access token 파싱 String accessToken = request.getHeader(HttpHeaders.AUTHORIZATION); validateToken(accessToken); @@ -150,7 +150,7 @@ public TokenDTO resolveTokenPair(HttpServletRequest request) { validateToken(refreshToken); // TODO 3. return - return TokenDTO.builder() + return TokenPairDTO.builder() .accessToken(accessToken.substring(JWT_TOKEN_PREFIX.length())) .refreshToken(refreshToken.substring(JWT_TOKEN_PREFIX.length())) .build(); @@ -193,7 +193,7 @@ public void validateRefreshToken(User user, String refreshToken) { } @Transactional - public TokenDTO updateTokenPair(User user) { + public TokenPairDTO updateTokenPair(User user) { // TODO 1. new access token, refresh token 발급 String newAccessToken = jwtLoginProvider.generateToken(user, TokenType.ACCESS); String newRefreshToken = jwtLoginProvider.generateToken(user, TokenType.REFRESH); @@ -205,7 +205,7 @@ public TokenDTO updateTokenPair(User user) { tokenStorage.updateTokenValue(newRefreshToken); // TODO 3. return - return TokenDTO.builder() + return TokenPairDTO.builder() .accessToken(newAccessToken) .refreshToken(newRefreshToken) .build(); diff --git a/src/main/java/space/space_spring/service/UserService.java b/src/main/java/space/space_spring/service/UserService.java index 4a26adbe..c6cc9124 100644 --- a/src/main/java/space/space_spring/service/UserService.java +++ b/src/main/java/space/space_spring/service/UserService.java @@ -7,7 +7,7 @@ import org.springframework.transaction.annotation.Transactional; import space.space_spring.dao.JwtRepository; import space.space_spring.dao.UserSpaceDao; -import space.space_spring.dto.jwt.TokenDTO; +import space.space_spring.dto.jwt.TokenPairDTO; import space.space_spring.dto.jwt.TokenType; import space.space_spring.dto.user.GetUserProfileListDto; import space.space_spring.dto.user.PostLoginDto; @@ -85,13 +85,13 @@ public PostLoginDto login(PostLoginDto.Request request) { jwtRepository.save(tokenStorage); // TODO 5. return - TokenDTO tokenDTO = TokenDTO.builder() + TokenPairDTO tokenPairDTO = TokenPairDTO.builder() .refreshToken(refreshToken) .accessToken(accessToken) .build(); return PostLoginDto.builder() - .tokenDTO(tokenDTO) + .TokenPairDTO(tokenPairDTO) .userId(userByEmail.getUserId()) .build(); } From d5329d86291e830ffd7c8f08010e714f76a4db4c Mon Sep 17 00:00:00 2001 From: seongjunnoh Date: Wed, 25 Sep 2024 17:27:04 +0900 Subject: [PATCH 25/26] =?UTF-8?q?refactor=20:=20JwtLoginProvider.getUserId?= =?UTF-8?q?FromToken=20=EB=A9=94=EC=84=9C=EB=93=9C=20=EC=88=98=EC=A0=95=20?= =?UTF-8?q?->=20=ED=8C=8C=EB=9D=BC=EB=AF=B8=ED=84=B0=EC=9D=98=20TokenType?= =?UTF-8?q?=20=EC=A0=9C=EA=B1=B0?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../interceptor/jwtLogin/JwtLoginAuthInterceptor.java | 2 +- .../interceptor/jwtSocket/JwtChannelInterceptor.java | 2 +- src/main/java/space/space_spring/jwt/JwtLoginProvider.java | 4 ++-- src/main/java/space/space_spring/service/OAuthService.java | 2 +- 4 files changed, 5 insertions(+), 5 deletions(-) diff --git a/src/main/java/space/space_spring/interceptor/jwtLogin/JwtLoginAuthInterceptor.java b/src/main/java/space/space_spring/interceptor/jwtLogin/JwtLoginAuthInterceptor.java index 7522cf31..498bf21e 100644 --- a/src/main/java/space/space_spring/interceptor/jwtLogin/JwtLoginAuthInterceptor.java +++ b/src/main/java/space/space_spring/interceptor/jwtLogin/JwtLoginAuthInterceptor.java @@ -36,7 +36,7 @@ public boolean preHandle(HttpServletRequest request, HttpServletResponse respons } // TODO 3. AT 의 payload 로 부터 userId 값 get - Long userIdFromToken = jwtLoginProvider.getUserIdFromToken(accessToken, TokenType.ACCESS); + Long userIdFromToken = jwtLoginProvider.getUserIdFromAccessToken(accessToken); request.setAttribute("userId", userIdFromToken); return true; diff --git a/src/main/java/space/space_spring/interceptor/jwtSocket/JwtChannelInterceptor.java b/src/main/java/space/space_spring/interceptor/jwtSocket/JwtChannelInterceptor.java index e2738886..773c5e29 100644 --- a/src/main/java/space/space_spring/interceptor/jwtSocket/JwtChannelInterceptor.java +++ b/src/main/java/space/space_spring/interceptor/jwtSocket/JwtChannelInterceptor.java @@ -33,7 +33,7 @@ public Message preSend(Message message, MessageChannel channel) { String validatedToken = validateAccessToken(jwtToken); // 검증 후 사용자 정보를 세션에 저장 - Long userId = jwtLoginProvider.getUserIdFromToken(validatedToken, TokenType.ACCESS); + Long userId = jwtLoginProvider.getUserIdFromAccessToken(validatedToken); accessor.getSessionAttributes().put("userId", userId); } return message; diff --git a/src/main/java/space/space_spring/jwt/JwtLoginProvider.java b/src/main/java/space/space_spring/jwt/JwtLoginProvider.java index 31242bb8..70124800 100644 --- a/src/main/java/space/space_spring/jwt/JwtLoginProvider.java +++ b/src/main/java/space/space_spring/jwt/JwtLoginProvider.java @@ -102,10 +102,10 @@ public boolean isExpiredToken(String token, TokenType tokenType) { } - public Long getUserIdFromToken(String token, TokenType tokenType) { + public Long getUserIdFromAccessToken(String token) { try { Jws claims = Jwts.parserBuilder() - .setSigningKey(choiceSecretKey(tokenType)).build() + .setSigningKey(ACCESS_SECRET_KEY).build() .parseClaimsJws(token); return claims.getBody().get("userId", Long.class); } catch (ExpiredJwtException e) { diff --git a/src/main/java/space/space_spring/service/OAuthService.java b/src/main/java/space/space_spring/service/OAuthService.java index 47165291..ef4abfbf 100644 --- a/src/main/java/space/space_spring/service/OAuthService.java +++ b/src/main/java/space/space_spring/service/OAuthService.java @@ -212,7 +212,7 @@ public TokenPairDTO updateTokenPair(User user) { } public User getUserByAccessToken(String accessToken) { - Long userIdFromToken = jwtLoginProvider.getUserIdFromToken(accessToken, TokenType.ACCESS); + Long userIdFromToken = jwtLoginProvider.getUserIdFromAccessToken(accessToken); return userRepository.findByUserId(userIdFromToken) .orElseThrow(() -> new CustomException(USER_NOT_FOUND)); From 8b966743a479a544f8b44ef2abd5cc50a6b6d4fc Mon Sep 17 00:00:00 2001 From: seongjunnoh Date: Thu, 26 Sep 2024 00:47:45 +0900 Subject: [PATCH 26/26] =?UTF-8?q?refactor=20:=20user,=20auth=20=EB=8F=84?= =?UTF-8?q?=EB=A9=94=EC=9D=B8=20=EC=83=9D=EC=84=B1=20&=20=EB=8F=84?= =?UTF-8?q?=EB=A9=94=EC=9D=B8=20=EA=B5=AC=EC=A1=B0=EB=A1=9C=20=EB=B3=80?= =?UTF-8?q?=EA=B2=BD?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../space/space_spring/dao/UserSpaceDao.java | 7 +- .../java/space/space_spring/domain/.DS_Store | Bin 0 -> 6148 bytes .../OAuth}/controller/OAuthController.java | 42 +---- .../OAuth/service/OAuthService.java | 110 +++++++++++++ .../auth/controller/AuthController.java | 45 ++++++ .../auth/service/AuthService.java | 72 +++++++++ .../jwt/controller/JwtController.java | 51 ++++++ .../jwt/model}/TokenPairDTO.java | 2 +- .../authorization/jwt/model/TokenType.java | 6 + .../jwt/repository}/JwtRepository.java | 2 +- .../jwt/service/JwtService.java} | 150 ++++-------------- .../user}/controller/UserController.java | 31 +--- .../user/model}/GetUserProfileListDto.java | 3 +- .../user/model}/PostLoginDto.java | 4 +- .../user/model}/dto/SpaceChoiceInfo.java | 2 +- .../user/model}/dto/SpaceChoiceViewDto.java | 2 +- .../model}/request/PostUserLoginRequest.java | 2 +- .../model}/request/PostUserSignupRequest.java | 2 +- .../response/GetSpaceInfoForUserResponse.java | 4 +- .../user/repository}/UserDao.java | 2 +- .../user/repository}/UserRepository.java | 2 +- .../user}/service/UserService.java | 59 +------ .../space/space_spring/dto/jwt/TokenType.java | 6 - .../UserSpaceValidationInterceptor.java | 2 +- .../jwtLogin/JwtLoginAuthInterceptor.java | 5 +- .../jwtSocket/JwtChannelInterceptor.java | 2 +- .../space_spring/jwt/JwtLoginProvider.java | 2 +- .../space_spring/service/PayService.java | 4 +- .../space_spring/service/SpaceService.java | 3 +- .../service/VoiceRoomService.java | 7 +- .../space_spring/util/user/UserUtils.java | 2 +- .../util/userSpace/MemoryUserSpaceUtils.java | 2 +- 32 files changed, 356 insertions(+), 279 deletions(-) create mode 100644 src/main/java/space/space_spring/domain/.DS_Store rename src/main/java/space/space_spring/{ => domain/authorization/OAuth}/controller/OAuthController.java (64%) create mode 100644 src/main/java/space/space_spring/domain/authorization/OAuth/service/OAuthService.java create mode 100644 src/main/java/space/space_spring/domain/authorization/auth/controller/AuthController.java create mode 100644 src/main/java/space/space_spring/domain/authorization/auth/service/AuthService.java create mode 100644 src/main/java/space/space_spring/domain/authorization/jwt/controller/JwtController.java rename src/main/java/space/space_spring/{dto/jwt => domain/authorization/jwt/model}/TokenPairDTO.java (81%) create mode 100644 src/main/java/space/space_spring/domain/authorization/jwt/model/TokenType.java rename src/main/java/space/space_spring/{dao => domain/authorization/jwt/repository}/JwtRepository.java (86%) rename src/main/java/space/space_spring/{service/OAuthService.java => domain/authorization/jwt/service/JwtService.java} (53%) rename src/main/java/space/space_spring/{ => domain/user}/controller/UserController.java (61%) rename src/main/java/space/space_spring/{dto/user => domain/user/model}/GetUserProfileListDto.java (85%) rename src/main/java/space/space_spring/{dto/user => domain/user/model}/PostLoginDto.java (89%) rename src/main/java/space/space_spring/{dto/user => domain/user/model}/dto/SpaceChoiceInfo.java (80%) rename src/main/java/space/space_spring/{dto/user => domain/user/model}/dto/SpaceChoiceViewDto.java (82%) rename src/main/java/space/space_spring/{dto/user => domain/user/model}/request/PostUserLoginRequest.java (93%) rename src/main/java/space/space_spring/{dto/user => domain/user/model}/request/PostUserSignupRequest.java (94%) rename src/main/java/space/space_spring/{dto/user => domain/user/model}/response/GetSpaceInfoForUserResponse.java (69%) rename src/main/java/space/space_spring/{dao => domain/user/repository}/UserDao.java (98%) rename src/main/java/space/space_spring/{dao => domain/user/repository}/UserRepository.java (89%) rename src/main/java/space/space_spring/{ => domain/user}/service/UserService.java (62%) delete mode 100644 src/main/java/space/space_spring/dto/jwt/TokenType.java diff --git a/src/main/java/space/space_spring/dao/UserSpaceDao.java b/src/main/java/space/space_spring/dao/UserSpaceDao.java index 4dbad3eb..147e4175 100644 --- a/src/main/java/space/space_spring/dao/UserSpaceDao.java +++ b/src/main/java/space/space_spring/dao/UserSpaceDao.java @@ -5,8 +5,8 @@ import jakarta.persistence.TypedQuery; import org.springframework.stereotype.Repository; import org.springframework.transaction.annotation.Transactional; -import space.space_spring.dto.user.dto.SpaceChoiceInfo; -import space.space_spring.dto.user.dto.SpaceChoiceViewDto; +import space.space_spring.domain.user.model.dto.SpaceChoiceInfo; +import space.space_spring.domain.user.model.dto.SpaceChoiceViewDto; import space.space_spring.dto.userSpace.UserInfoInSpace; import space.space_spring.entity.Space; import space.space_spring.entity.User; @@ -14,9 +14,6 @@ import space.space_spring.entity.enumStatus.UserSpaceAuth; import java.util.*; -import java.util.stream.Stream; - -import static space.space_spring.entity.enumStatus.UserSpaceAuth.MANAGER; @Repository public class UserSpaceDao { diff --git a/src/main/java/space/space_spring/domain/.DS_Store b/src/main/java/space/space_spring/domain/.DS_Store new file mode 100644 index 0000000000000000000000000000000000000000..cf1810f3a12ab491bfe87f5bb0b434060947e4bc GIT binary patch literal 6148 zcmeHKJ8Hu~5S>X}7=l5i%e_Kwun6Y_zJLP(+Yn?hQHoTmaxNduZ$1Qsz@Urf@S%CL=7getJI*g& zE?NT_sQ?uiEASlK#`^yo{Kou0CUHjvsKCEcKo^_sro}5|Z=JlH_1Xg8!L8;3H^bT~ n2;Po?-j1=ccD(kYs4KR{^O`sWIvshZ1Nk#xy3nY=qZPOU7(o{w literal 0 HcmV?d00001 diff --git a/src/main/java/space/space_spring/controller/OAuthController.java b/src/main/java/space/space_spring/domain/authorization/OAuth/controller/OAuthController.java similarity index 64% rename from src/main/java/space/space_spring/controller/OAuthController.java rename to src/main/java/space/space_spring/domain/authorization/OAuth/controller/OAuthController.java index dc1b7fa1..410350d4 100644 --- a/src/main/java/space/space_spring/controller/OAuthController.java +++ b/src/main/java/space/space_spring/domain/authorization/OAuth/controller/OAuthController.java @@ -1,17 +1,16 @@ -package space.space_spring.controller; +package space.space_spring.domain.authorization.OAuth.controller; import com.fasterxml.jackson.core.JsonProcessingException; -import jakarta.servlet.http.HttpServletRequest; import jakarta.servlet.http.HttpServletResponse; import lombok.RequiredArgsConstructor; import lombok.extern.slf4j.Slf4j; import org.springframework.beans.factory.annotation.Value; import org.springframework.web.bind.annotation.*; -import space.space_spring.dto.jwt.TokenPairDTO; +import space.space_spring.domain.authorization.jwt.service.JwtService; +import space.space_spring.domain.authorization.jwt.model.TokenPairDTO; import space.space_spring.dto.oAuth.KakaoInfo; import space.space_spring.entity.User; -import space.space_spring.response.BaseResponse; -import space.space_spring.service.OAuthService; +import space.space_spring.domain.authorization.OAuth.service.OAuthService; import java.io.IOException; @@ -22,6 +21,7 @@ public class OAuthController { private final OAuthService oAuthService; + private final JwtService jwtService; @Value("${oauth.kakao.client.id}") private String clientId; @@ -67,10 +67,10 @@ public void kakaoCallback(@RequestParam(name = "code") String code, HttpServletR User userByOAuthInfo = oAuthService.findUserByOAuthInfo(kakaoInfo); // TODO 5. 카카오 로그인 유저에게 jwt 발급 - TokenPairDTO tokenPairDTO = oAuthService.provideJwtToOAuthUser(userByOAuthInfo); + TokenPairDTO tokenPairDTO = jwtService.provideJwtToOAuthUser(userByOAuthInfo); // TODO 6. 카카오 로그인 유저에게 발급한 refresh token을 db에 저장 - oAuthService.updateRefreshToken(userByOAuthInfo, tokenPairDTO.getRefreshToken()); + jwtService.updateRefreshToken(userByOAuthInfo, tokenPairDTO.getRefreshToken()); System.out.println("tokenPairDTO.getAccessToken() = " + tokenPairDTO.getAccessToken()); System.out.println("tokenPairDTO.getRefreshToken() = " + tokenPairDTO.getRefreshToken()); @@ -88,32 +88,4 @@ public void kakaoCallback(@RequestParam(name = "code") String code, HttpServletR response.sendRedirect(redirectUrl); } - /** - * 엑세스 토큰 갱신 요청 처리 - * -> 엑세스 토큰, 리프레시 토큰 갱신 (RTR 패턴) - */ - @PostMapping("/new-token") - public BaseResponse updateAccessToken(HttpServletRequest request, HttpServletResponse response) throws IOException { - // access token, refresh token 파싱 - TokenPairDTO tokenPairDTO = oAuthService.resolveTokenPair(request); - - // access token 로부터 user find - User userByAccessToken = oAuthService.getUserByAccessToken(tokenPairDTO.getAccessToken()); - - // refresh token 유효성 검사 - oAuthService.validateRefreshToken(userByAccessToken, tokenPairDTO.getRefreshToken()); - - // access token, refresh token 새로 발급 - TokenPairDTO newTokenPairDTO = oAuthService.updateTokenPair(userByAccessToken); - - // response header에 새로 발급한 token pair set - response.setHeader("Authorization-refresh", "Bearer " + newTokenPairDTO.getRefreshToken()); - response.setHeader("Authorization", "Bearer " + newTokenPairDTO.getAccessToken()); - - System.out.println("tokenPairDTO.getAccessToken() = " + newTokenPairDTO.getAccessToken()); - System.out.println("tokenPairDTO.getRefreshToken() = " + newTokenPairDTO.getRefreshToken()); - - // return - return new BaseResponse<>("토큰 갱신 요청 성공"); - } } diff --git a/src/main/java/space/space_spring/domain/authorization/OAuth/service/OAuthService.java b/src/main/java/space/space_spring/domain/authorization/OAuth/service/OAuthService.java new file mode 100644 index 00000000..e4934b5c --- /dev/null +++ b/src/main/java/space/space_spring/domain/authorization/OAuth/service/OAuthService.java @@ -0,0 +1,110 @@ +package space.space_spring.domain.authorization.OAuth.service; + +import com.fasterxml.jackson.core.JsonProcessingException; +import com.fasterxml.jackson.databind.JsonNode; +import com.fasterxml.jackson.databind.ObjectMapper; +import lombok.RequiredArgsConstructor; +import org.springframework.http.HttpEntity; +import org.springframework.http.HttpHeaders; +import org.springframework.http.HttpMethod; +import org.springframework.http.ResponseEntity; +import org.springframework.stereotype.Service; +import org.springframework.transaction.annotation.Transactional; +import org.springframework.util.LinkedMultiValueMap; +import org.springframework.util.MultiValueMap; +import org.springframework.web.client.RestTemplate; +import space.space_spring.domain.user.repository.UserDao; +import space.space_spring.dto.oAuth.KakaoInfo; +import space.space_spring.entity.User; +import space.space_spring.util.user.UserUtils; + +import static space.space_spring.entity.enumStatus.UserSignupType.KAKAO; + +@Service +@RequiredArgsConstructor +public class OAuthService { + + private final UserUtils userUtils; + private final UserDao userDao; + + + /** + * 카카오 인증 서버가 전달해준 유저의 인가코드로 토큰 발급 요청 + */ + public String getAccessToken(String code, String clientId, String redirectUri, String clientSecret) throws JsonProcessingException { + + // TODO 1. HTTP Header 생성 + HttpHeaders headers = new HttpHeaders(); + headers.add("Content-type", "application/x-www-form-urlencoded;charset=utf-8"); + + // TODO 2. HTTP Body 생성 + MultiValueMap body = new LinkedMultiValueMap<>(); + body.add("grant_type", "authorization_code"); + body.add("client_id", clientId); + body.add("redirect_uri", redirectUri); + body.add("code", code); + body.add("client_secret", clientSecret); + + // TODO 3. 카카오 인증 서버로 HTTP 요청 보내기 + HttpEntity> kakaoTokenRequest = new HttpEntity<>(body, headers); + RestTemplate rt = new RestTemplate(); + ResponseEntity response = rt.exchange( + "https://kauth.kakao.com/oauth/token", + HttpMethod.POST, + kakaoTokenRequest, + String.class + ); + + // TODO 4. 카카오 인증 서버로부터의 HTTP 응답 (JSON) -> 액세스 토큰만 파싱 + String responseBody = response.getBody(); + ObjectMapper objectMapper = new ObjectMapper(); + JsonNode jsonNode = objectMapper.readTree(responseBody); + + return jsonNode.get("access_token").asText(); + } + + /** + * 카카오 인증 서버로부터 받은 access token 으로 해당 유저의 사용자 정보 가져오기 + */ + public KakaoInfo getKakaoInfo(String accessToken) throws JsonProcessingException { + + // TODO 1. HTTP Header 생성 + HttpHeaders headers = new HttpHeaders(); + headers.add("Authorization", "Bearer " + accessToken); + headers.add("Content-type", "application/x-www-form-urlencoded;charset=utf-8"); + + // TODO 2. 카카오 api 서버로 HTTP 요청 보내기 + HttpEntity> kakaoUserInfoRequest = new HttpEntity<>(headers); + RestTemplate rt = new RestTemplate(); + ResponseEntity response = rt.exchange( + "https://kapi.kakao.com/v2/user/me", + HttpMethod.POST, + kakaoUserInfoRequest, + String.class + ); + + // TODO 3. responseBody에 있는 정보 꺼내기 + String responseBody = response.getBody(); + ObjectMapper objectMapper = new ObjectMapper(); + JsonNode jsonNode = objectMapper.readTree(responseBody); + + // 유저의 이메일, nickname 정보 get + String email = jsonNode.get("kakao_account").get("email").asText(); + String nickname = jsonNode.get("properties").get("nickname").asText(); + + return new KakaoInfo(nickname, email); + } + + @Transactional + public User findUserByOAuthInfo(KakaoInfo kakaoInfo) { + String email = kakaoInfo.getEmail(); + String nickname = kakaoInfo.getNickName(); + + // 카카오 서버로부터 얻은 정보로 회원가입 or 로그인 + return userUtils.findOrCreateUserForOAuthInfo(email, nickname, KAKAO); + } + + + + +} diff --git a/src/main/java/space/space_spring/domain/authorization/auth/controller/AuthController.java b/src/main/java/space/space_spring/domain/authorization/auth/controller/AuthController.java new file mode 100644 index 00000000..c2b86e10 --- /dev/null +++ b/src/main/java/space/space_spring/domain/authorization/auth/controller/AuthController.java @@ -0,0 +1,45 @@ +package space.space_spring.domain.authorization.auth.controller; + +import jakarta.servlet.http.HttpServletResponse; +import lombok.RequiredArgsConstructor; +import org.springframework.validation.BindingResult; +import org.springframework.validation.annotation.Validated; +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 space.space_spring.domain.authorization.auth.service.AuthService; +import space.space_spring.domain.user.model.PostLoginDto; +import space.space_spring.exception.CustomException; +import space.space_spring.response.BaseResponse; + +import static space.space_spring.response.status.BaseExceptionResponseStatus.INVALID_USER_LOGIN; +import static space.space_spring.util.bindingResult.BindingResultUtils.getErrorMessage; + +@RestController +@RequiredArgsConstructor +@RequestMapping("/user") +public class AuthController { + + private final AuthService authService; + + /** + * 로그인 + */ + @PostMapping("/login") + public BaseResponse login(@Validated @RequestBody PostLoginDto.Request request, BindingResult bindingResult, HttpServletResponse response) { + if (bindingResult.hasErrors()) { + throw new CustomException(INVALID_USER_LOGIN, getErrorMessage(bindingResult)); + } + + PostLoginDto login = authService.login(request); + + System.out.println("login.getTokenPairDTO().getRefreshToken() = " + login.getTokenPairDTO().getRefreshToken()); + System.out.println("login.getTokenPairDTO().getAccessToken() = " + login.getTokenPairDTO().getAccessToken()); + + response.setHeader("Authorization-refresh", "Bearer " + login.getTokenPairDTO().getRefreshToken()); + response.setHeader("Authorization", "Bearer " + login.getTokenPairDTO().getAccessToken()); + + return new BaseResponse<>(new PostLoginDto.Response(login.getUserId())); + } +} diff --git a/src/main/java/space/space_spring/domain/authorization/auth/service/AuthService.java b/src/main/java/space/space_spring/domain/authorization/auth/service/AuthService.java new file mode 100644 index 00000000..25484a2d --- /dev/null +++ b/src/main/java/space/space_spring/domain/authorization/auth/service/AuthService.java @@ -0,0 +1,72 @@ +package space.space_spring.domain.authorization.auth.service; + +import lombok.RequiredArgsConstructor; +import lombok.extern.slf4j.Slf4j; +import org.springframework.security.crypto.password.PasswordEncoder; +import org.springframework.stereotype.Service; +import org.springframework.transaction.annotation.Transactional; +import space.space_spring.domain.authorization.jwt.model.TokenPairDTO; +import space.space_spring.domain.authorization.jwt.model.TokenType; +import space.space_spring.domain.authorization.jwt.repository.JwtRepository; +import space.space_spring.domain.user.model.PostLoginDto; +import space.space_spring.entity.TokenStorage; +import space.space_spring.entity.User; +import space.space_spring.exception.CustomException; +import space.space_spring.jwt.JwtLoginProvider; +import space.space_spring.util.user.UserUtils; + +import static space.space_spring.entity.enumStatus.UserSignupType.LOCAL; +import static space.space_spring.response.status.BaseExceptionResponseStatus.PASSWORD_NO_MATCH; + +@Service +@RequiredArgsConstructor +@Transactional(readOnly = true) +@Slf4j +public class AuthService { + + private final JwtLoginProvider jwtLoginProvider; + private final JwtRepository jwtRepository; + private final PasswordEncoder passwordEncoder; + private final UserUtils userUtils; + + + @Transactional + public PostLoginDto login(PostLoginDto.Request request) { + // TODO 1. 이메일 존재 여부 확인(아이디 존재 여부 확인) + User userByEmail = userUtils.findUserByEmail(request.getEmail(), LOCAL); + log.info("userByEmail.getUserId: {}", userByEmail.getUserId()); + + // TODO 2. 비밀번호 일치 여부 확인 + validatePassword(userByEmail, request.getPassword()); + + // TODO 3. JWT 발급 -> access token, refresh token 2개 발급 + String accessToken = jwtLoginProvider.generateToken(userByEmail, TokenType.ACCESS); + String refreshToken = jwtLoginProvider.generateToken(userByEmail, TokenType.REFRESH); + + // TODO 4. refresh token db에 저장 + TokenStorage tokenStorage = TokenStorage.builder() + .user(userByEmail) + .tokenValue(refreshToken) + .build(); + jwtRepository.save(tokenStorage); + + // TODO 5. return + TokenPairDTO tokenPairDTO = TokenPairDTO.builder() + .refreshToken(refreshToken) + .accessToken(accessToken) + .build(); + + return PostLoginDto.builder() + .TokenPairDTO(tokenPairDTO) + .userId(userByEmail.getUserId()) + .build(); + } + + private void validatePassword(User userByEmail, String password) { + String encodePassword = userByEmail.getPassword(); + if(!passwordEncoder.matches(password,encodePassword)){ + throw new CustomException(PASSWORD_NO_MATCH); + } + + } +} diff --git a/src/main/java/space/space_spring/domain/authorization/jwt/controller/JwtController.java b/src/main/java/space/space_spring/domain/authorization/jwt/controller/JwtController.java new file mode 100644 index 00000000..b2cd2d93 --- /dev/null +++ b/src/main/java/space/space_spring/domain/authorization/jwt/controller/JwtController.java @@ -0,0 +1,51 @@ +package space.space_spring.domain.authorization.jwt.controller; + +import jakarta.servlet.http.HttpServletRequest; +import jakarta.servlet.http.HttpServletResponse; +import lombok.RequiredArgsConstructor; +import org.springframework.web.bind.annotation.PostMapping; +import org.springframework.web.bind.annotation.RequestMapping; +import org.springframework.web.bind.annotation.RestController; +import space.space_spring.domain.authorization.jwt.service.JwtService; +import space.space_spring.domain.authorization.jwt.model.TokenPairDTO; +import space.space_spring.entity.User; +import space.space_spring.response.BaseResponse; + +import java.io.IOException; + +@RestController +@RequiredArgsConstructor +@RequestMapping("/jwt") +public class JwtController { + + private final JwtService jwtService; + + /** + * 엑세스 토큰 갱신 요청 처리 + * -> 엑세스 토큰, 리프레시 토큰 갱신 (RTR 패턴) + */ + @PostMapping("/new-token") + public BaseResponse updateAccessToken(HttpServletRequest request, HttpServletResponse response) throws IOException { + // access token, refresh token 파싱 + TokenPairDTO tokenPairDTO = jwtService.resolveTokenPair(request); + + // access token 로부터 user find + User userByAccessToken = jwtService.getUserByAccessToken(tokenPairDTO.getAccessToken()); + + // refresh token 유효성 검사 + jwtService.validateRefreshToken(userByAccessToken, tokenPairDTO.getRefreshToken()); + + // access token, refresh token 새로 발급 + TokenPairDTO newTokenPairDTO = jwtService.updateTokenPair(userByAccessToken); + + // response header에 새로 발급한 token pair set + response.setHeader("Authorization-refresh", "Bearer " + newTokenPairDTO.getRefreshToken()); + response.setHeader("Authorization", "Bearer " + newTokenPairDTO.getAccessToken()); + + System.out.println("tokenPairDTO.getAccessToken() = " + newTokenPairDTO.getAccessToken()); + System.out.println("tokenPairDTO.getRefreshToken() = " + newTokenPairDTO.getRefreshToken()); + + // return + return new BaseResponse<>("토큰 갱신 요청 성공"); + } +} diff --git a/src/main/java/space/space_spring/dto/jwt/TokenPairDTO.java b/src/main/java/space/space_spring/domain/authorization/jwt/model/TokenPairDTO.java similarity index 81% rename from src/main/java/space/space_spring/dto/jwt/TokenPairDTO.java rename to src/main/java/space/space_spring/domain/authorization/jwt/model/TokenPairDTO.java index c2dfdc64..79f64f26 100644 --- a/src/main/java/space/space_spring/dto/jwt/TokenPairDTO.java +++ b/src/main/java/space/space_spring/domain/authorization/jwt/model/TokenPairDTO.java @@ -1,4 +1,4 @@ -package space.space_spring.dto.jwt; +package space.space_spring.domain.authorization.jwt.model; import lombok.AllArgsConstructor; import lombok.Builder; diff --git a/src/main/java/space/space_spring/domain/authorization/jwt/model/TokenType.java b/src/main/java/space/space_spring/domain/authorization/jwt/model/TokenType.java new file mode 100644 index 00000000..aa5f5a1e --- /dev/null +++ b/src/main/java/space/space_spring/domain/authorization/jwt/model/TokenType.java @@ -0,0 +1,6 @@ +package space.space_spring.domain.authorization.jwt.model; + +public enum TokenType { + REFRESH, + ACCESS +} diff --git a/src/main/java/space/space_spring/dao/JwtRepository.java b/src/main/java/space/space_spring/domain/authorization/jwt/repository/JwtRepository.java similarity index 86% rename from src/main/java/space/space_spring/dao/JwtRepository.java rename to src/main/java/space/space_spring/domain/authorization/jwt/repository/JwtRepository.java index e336dd4e..dad962d3 100644 --- a/src/main/java/space/space_spring/dao/JwtRepository.java +++ b/src/main/java/space/space_spring/domain/authorization/jwt/repository/JwtRepository.java @@ -1,4 +1,4 @@ -package space.space_spring.dao; +package space.space_spring.domain.authorization.jwt.repository; import org.springframework.data.jpa.repository.JpaRepository; import org.springframework.stereotype.Repository; diff --git a/src/main/java/space/space_spring/service/OAuthService.java b/src/main/java/space/space_spring/domain/authorization/jwt/service/JwtService.java similarity index 53% rename from src/main/java/space/space_spring/service/OAuthService.java rename to src/main/java/space/space_spring/domain/authorization/jwt/service/JwtService.java index ef4abfbf..1b3c65af 100644 --- a/src/main/java/space/space_spring/service/OAuthService.java +++ b/src/main/java/space/space_spring/domain/authorization/jwt/service/JwtService.java @@ -1,25 +1,14 @@ -package space.space_spring.service; +package space.space_spring.domain.authorization.jwt.service; -import com.fasterxml.jackson.core.JsonProcessingException; -import com.fasterxml.jackson.databind.JsonNode; -import com.fasterxml.jackson.databind.ObjectMapper; import jakarta.servlet.http.HttpServletRequest; import lombok.RequiredArgsConstructor; -import org.springframework.http.HttpEntity; import org.springframework.http.HttpHeaders; -import org.springframework.http.HttpMethod; -import org.springframework.http.ResponseEntity; import org.springframework.stereotype.Service; import org.springframework.transaction.annotation.Transactional; -import org.springframework.util.LinkedMultiValueMap; -import org.springframework.util.MultiValueMap; -import org.springframework.web.client.RestTemplate; -import space.space_spring.dao.JwtRepository; -import space.space_spring.dao.UserDao; -import space.space_spring.dao.UserRepository; -import space.space_spring.dto.jwt.TokenPairDTO; -import space.space_spring.dto.jwt.TokenType; -import space.space_spring.dto.oAuth.KakaoInfo; +import space.space_spring.domain.authorization.jwt.repository.JwtRepository; +import space.space_spring.domain.user.repository.UserRepository; +import space.space_spring.domain.authorization.jwt.model.TokenPairDTO; +import space.space_spring.domain.authorization.jwt.model.TokenType; import space.space_spring.entity.TokenStorage; import space.space_spring.entity.User; import space.space_spring.exception.CustomException; @@ -28,117 +17,19 @@ import space.space_spring.exception.jwt.unauthorized.JwtExpiredTokenException; import space.space_spring.exception.jwt.unauthorized.JwtUnauthorizedTokenException; import space.space_spring.jwt.JwtLoginProvider; -import space.space_spring.util.user.UserUtils; -import static space.space_spring.entity.enumStatus.UserSignupType.KAKAO; import static space.space_spring.response.status.BaseExceptionResponseStatus.*; -import static space.space_spring.response.status.BaseExceptionResponseStatus.UNSUPPORTED_TOKEN_TYPE; @Service @RequiredArgsConstructor -public class OAuthService { +public class JwtService { - private final UserUtils userUtils; - private final JwtLoginProvider jwtLoginProvider; - private final UserDao userDao; private final JwtRepository jwtRepository; + private final JwtLoginProvider jwtLoginProvider; private final UserRepository userRepository; private static final String JWT_TOKEN_PREFIX = "Bearer "; - /** - * 카카오 인증 서버가 전달해준 유저의 인가코드로 토큰 발급 요청 - */ - public String getAccessToken(String code, String clientId, String redirectUri, String clientSecret) throws JsonProcessingException { - - // TODO 1. HTTP Header 생성 - HttpHeaders headers = new HttpHeaders(); - headers.add("Content-type", "application/x-www-form-urlencoded;charset=utf-8"); - - // TODO 2. HTTP Body 생성 - MultiValueMap body = new LinkedMultiValueMap<>(); - body.add("grant_type", "authorization_code"); - body.add("client_id", clientId); - body.add("redirect_uri", redirectUri); - body.add("code", code); - body.add("client_secret", clientSecret); - - // TODO 3. 카카오 인증 서버로 HTTP 요청 보내기 - HttpEntity> kakaoTokenRequest = new HttpEntity<>(body, headers); - RestTemplate rt = new RestTemplate(); - ResponseEntity response = rt.exchange( - "https://kauth.kakao.com/oauth/token", - HttpMethod.POST, - kakaoTokenRequest, - String.class - ); - - // TODO 4. 카카오 인증 서버로부터의 HTTP 응답 (JSON) -> 액세스 토큰만 파싱 - String responseBody = response.getBody(); - ObjectMapper objectMapper = new ObjectMapper(); - JsonNode jsonNode = objectMapper.readTree(responseBody); - - return jsonNode.get("access_token").asText(); - } - - /** - * 카카오 인증 서버로부터 받은 access token 으로 해당 유저의 사용자 정보 가져오기 - */ - public KakaoInfo getKakaoInfo(String accessToken) throws JsonProcessingException { - - // TODO 1. HTTP Header 생성 - HttpHeaders headers = new HttpHeaders(); - headers.add("Authorization", "Bearer " + accessToken); - headers.add("Content-type", "application/x-www-form-urlencoded;charset=utf-8"); - - // TODO 2. 카카오 api 서버로 HTTP 요청 보내기 - HttpEntity> kakaoUserInfoRequest = new HttpEntity<>(headers); - RestTemplate rt = new RestTemplate(); - ResponseEntity response = rt.exchange( - "https://kapi.kakao.com/v2/user/me", - HttpMethod.POST, - kakaoUserInfoRequest, - String.class - ); - - // TODO 3. responseBody에 있는 정보 꺼내기 - String responseBody = response.getBody(); - ObjectMapper objectMapper = new ObjectMapper(); - JsonNode jsonNode = objectMapper.readTree(responseBody); - - // 유저의 이메일, nickname 정보 get - String email = jsonNode.get("kakao_account").get("email").asText(); - String nickname = jsonNode.get("properties").get("nickname").asText(); - - return new KakaoInfo(nickname, email); - } - - @Transactional - public User findUserByOAuthInfo(KakaoInfo kakaoInfo) { - String email = kakaoInfo.getEmail(); - String nickname = kakaoInfo.getNickName(); - - // 카카오 서버로부터 얻은 정보로 회원가입 or 로그인 - return userUtils.findOrCreateUserForOAuthInfo(email, nickname, KAKAO); - } - - public TokenPairDTO provideJwtToOAuthUser(User userByOAuthInfo) { - String accessToken = jwtLoginProvider.generateToken(userByOAuthInfo, TokenType.ACCESS); - String refreshToken = jwtLoginProvider.generateToken(userByOAuthInfo, TokenType.REFRESH); - - return TokenPairDTO.builder() - .accessToken(accessToken) - .refreshToken(refreshToken) - .build(); - } - - @Transactional - public void updateRefreshToken(User user, String refreshToken) { - TokenStorage tokenStorage = jwtRepository.findByUser(user) - .orElseThrow(() -> new JwtUnauthorizedTokenException(TOKEN_MISMATCH)); - - tokenStorage.updateTokenValue(refreshToken); - } public TokenPairDTO resolveTokenPair(HttpServletRequest request) { // TODO 1. access token 파싱 @@ -165,6 +56,13 @@ private void validateToken(String token) { } } + public User getUserByAccessToken(String accessToken) { + Long userIdFromToken = jwtLoginProvider.getUserIdFromAccessToken(accessToken); + + return userRepository.findByUserId(userIdFromToken) + .orElseThrow(() -> new CustomException(USER_NOT_FOUND)); + } + @Transactional public void validateRefreshToken(User user, String refreshToken) { TokenStorage tokenStorage = jwtRepository.findByUser(user) @@ -211,10 +109,22 @@ public TokenPairDTO updateTokenPair(User user) { .build(); } - public User getUserByAccessToken(String accessToken) { - Long userIdFromToken = jwtLoginProvider.getUserIdFromAccessToken(accessToken); + public TokenPairDTO provideJwtToOAuthUser(User userByOAuthInfo) { + String accessToken = jwtLoginProvider.generateToken(userByOAuthInfo, TokenType.ACCESS); + String refreshToken = jwtLoginProvider.generateToken(userByOAuthInfo, TokenType.REFRESH); - return userRepository.findByUserId(userIdFromToken) - .orElseThrow(() -> new CustomException(USER_NOT_FOUND)); + return TokenPairDTO.builder() + .accessToken(accessToken) + .refreshToken(refreshToken) + .build(); } + + @Transactional + public void updateRefreshToken(User user, String refreshToken) { + TokenStorage tokenStorage = jwtRepository.findByUser(user) + .orElseThrow(() -> new JwtUnauthorizedTokenException(TOKEN_MISMATCH)); + + tokenStorage.updateTokenValue(refreshToken); + } + } diff --git a/src/main/java/space/space_spring/controller/UserController.java b/src/main/java/space/space_spring/domain/user/controller/UserController.java similarity index 61% rename from src/main/java/space/space_spring/controller/UserController.java rename to src/main/java/space/space_spring/domain/user/controller/UserController.java index aa0ad77c..ccf0f455 100644 --- a/src/main/java/space/space_spring/controller/UserController.java +++ b/src/main/java/space/space_spring/domain/user/controller/UserController.java @@ -1,19 +1,17 @@ -package space.space_spring.controller; +package space.space_spring.domain.user.controller; -import jakarta.servlet.http.HttpServletResponse; import lombok.RequiredArgsConstructor; import lombok.extern.slf4j.Slf4j; import org.springframework.validation.BindingResult; import org.springframework.validation.annotation.Validated; import org.springframework.web.bind.annotation.*; -import space.space_spring.dto.user.GetUserProfileListDto; import space.space_spring.argumentResolver.jwtLogin.JwtLoginAuth; -import space.space_spring.dto.user.PostLoginDto; -import space.space_spring.dto.user.request.PostUserSignupRequest; -import space.space_spring.dto.user.response.GetSpaceInfoForUserResponse; +import space.space_spring.domain.user.model.GetUserProfileListDto; +import space.space_spring.domain.user.model.request.PostUserSignupRequest; +import space.space_spring.domain.user.model.response.GetSpaceInfoForUserResponse; import space.space_spring.exception.CustomException; import space.space_spring.response.BaseResponse; -import space.space_spring.service.UserService; +import space.space_spring.domain.user.service.UserService; import space.space_spring.util.userSpace.UserSpaceUtils; import static space.space_spring.response.status.BaseExceptionResponseStatus.*; @@ -42,25 +40,6 @@ public BaseResponse signup(@Validated @RequestBody PostUserSignupRequest return new BaseResponse<>("로컬 회원가입 성공"); } - /** - * 로그인 - */ - @PostMapping("/login") - public BaseResponse login(@Validated @RequestBody PostLoginDto.Request request, BindingResult bindingResult, HttpServletResponse response) { - if (bindingResult.hasErrors()) { - throw new CustomException(INVALID_USER_LOGIN, getErrorMessage(bindingResult)); - } - - PostLoginDto login = userService.login(request); - - System.out.println("login.getTokenPairDTO().getRefreshToken() = " + login.getTokenPairDTO().getRefreshToken()); - System.out.println("login.getTokenPairDTO().getAccessToken() = " + login.getTokenPairDTO().getAccessToken()); - - response.setHeader("Authorization-refresh", "Bearer " + login.getTokenPairDTO().getRefreshToken()); - response.setHeader("Authorization", "Bearer " + login.getTokenPairDTO().getAccessToken()); - - return new BaseResponse<>(new PostLoginDto.Response(login.getUserId())); - } /** * 유저가 속한 스페이스 리스트 diff --git a/src/main/java/space/space_spring/dto/user/GetUserProfileListDto.java b/src/main/java/space/space_spring/domain/user/model/GetUserProfileListDto.java similarity index 85% rename from src/main/java/space/space_spring/dto/user/GetUserProfileListDto.java rename to src/main/java/space/space_spring/domain/user/model/GetUserProfileListDto.java index 39899402..add4fec0 100644 --- a/src/main/java/space/space_spring/dto/user/GetUserProfileListDto.java +++ b/src/main/java/space/space_spring/domain/user/model/GetUserProfileListDto.java @@ -1,8 +1,7 @@ -package space.space_spring.dto.user; +package space.space_spring.domain.user.model; import lombok.AllArgsConstructor; import lombok.Getter; -import org.checkerframework.checker.units.qual.A; import java.util.List; diff --git a/src/main/java/space/space_spring/dto/user/PostLoginDto.java b/src/main/java/space/space_spring/domain/user/model/PostLoginDto.java similarity index 89% rename from src/main/java/space/space_spring/dto/user/PostLoginDto.java rename to src/main/java/space/space_spring/domain/user/model/PostLoginDto.java index 70327257..e33d2ba0 100644 --- a/src/main/java/space/space_spring/dto/user/PostLoginDto.java +++ b/src/main/java/space/space_spring/domain/user/model/PostLoginDto.java @@ -1,9 +1,9 @@ -package space.space_spring.dto.user; +package space.space_spring.domain.user.model; import jakarta.validation.constraints.NotBlank; import jakarta.validation.constraints.Pattern; import lombok.*; -import space.space_spring.dto.jwt.TokenPairDTO; +import space.space_spring.domain.authorization.jwt.model.TokenPairDTO; @Getter @NoArgsConstructor diff --git a/src/main/java/space/space_spring/dto/user/dto/SpaceChoiceInfo.java b/src/main/java/space/space_spring/domain/user/model/dto/SpaceChoiceInfo.java similarity index 80% rename from src/main/java/space/space_spring/dto/user/dto/SpaceChoiceInfo.java rename to src/main/java/space/space_spring/domain/user/model/dto/SpaceChoiceInfo.java index c62eb499..60d86060 100644 --- a/src/main/java/space/space_spring/dto/user/dto/SpaceChoiceInfo.java +++ b/src/main/java/space/space_spring/domain/user/model/dto/SpaceChoiceInfo.java @@ -1,4 +1,4 @@ -package space.space_spring.dto.user.dto; +package space.space_spring.domain.user.model.dto; import lombok.AllArgsConstructor; import lombok.Getter; diff --git a/src/main/java/space/space_spring/dto/user/dto/SpaceChoiceViewDto.java b/src/main/java/space/space_spring/domain/user/model/dto/SpaceChoiceViewDto.java similarity index 82% rename from src/main/java/space/space_spring/dto/user/dto/SpaceChoiceViewDto.java rename to src/main/java/space/space_spring/domain/user/model/dto/SpaceChoiceViewDto.java index 64f58dbe..c4b4bf2e 100644 --- a/src/main/java/space/space_spring/dto/user/dto/SpaceChoiceViewDto.java +++ b/src/main/java/space/space_spring/domain/user/model/dto/SpaceChoiceViewDto.java @@ -1,4 +1,4 @@ -package space.space_spring.dto.user.dto; +package space.space_spring.domain.user.model.dto; import lombok.AllArgsConstructor; import lombok.Getter; diff --git a/src/main/java/space/space_spring/dto/user/request/PostUserLoginRequest.java b/src/main/java/space/space_spring/domain/user/model/request/PostUserLoginRequest.java similarity index 93% rename from src/main/java/space/space_spring/dto/user/request/PostUserLoginRequest.java rename to src/main/java/space/space_spring/domain/user/model/request/PostUserLoginRequest.java index 763beb83..00640b9a 100644 --- a/src/main/java/space/space_spring/dto/user/request/PostUserLoginRequest.java +++ b/src/main/java/space/space_spring/domain/user/model/request/PostUserLoginRequest.java @@ -1,4 +1,4 @@ -package space.space_spring.dto.user.request; +package space.space_spring.domain.user.model.request; import jakarta.validation.constraints.NotBlank; import jakarta.validation.constraints.Pattern; diff --git a/src/main/java/space/space_spring/dto/user/request/PostUserSignupRequest.java b/src/main/java/space/space_spring/domain/user/model/request/PostUserSignupRequest.java similarity index 94% rename from src/main/java/space/space_spring/dto/user/request/PostUserSignupRequest.java rename to src/main/java/space/space_spring/domain/user/model/request/PostUserSignupRequest.java index bf797af5..1258ab0d 100644 --- a/src/main/java/space/space_spring/dto/user/request/PostUserSignupRequest.java +++ b/src/main/java/space/space_spring/domain/user/model/request/PostUserSignupRequest.java @@ -1,4 +1,4 @@ -package space.space_spring.dto.user.request; +package space.space_spring.domain.user.model.request; import jakarta.validation.constraints.NotBlank; import jakarta.validation.constraints.Pattern; diff --git a/src/main/java/space/space_spring/dto/user/response/GetSpaceInfoForUserResponse.java b/src/main/java/space/space_spring/domain/user/model/response/GetSpaceInfoForUserResponse.java similarity index 69% rename from src/main/java/space/space_spring/dto/user/response/GetSpaceInfoForUserResponse.java rename to src/main/java/space/space_spring/domain/user/model/response/GetSpaceInfoForUserResponse.java index 86f73c48..e9b60a0f 100644 --- a/src/main/java/space/space_spring/dto/user/response/GetSpaceInfoForUserResponse.java +++ b/src/main/java/space/space_spring/domain/user/model/response/GetSpaceInfoForUserResponse.java @@ -1,8 +1,8 @@ -package space.space_spring.dto.user.response; +package space.space_spring.domain.user.model.response; import lombok.AllArgsConstructor; import lombok.Getter; -import space.space_spring.dto.user.dto.SpaceChoiceInfo; +import space.space_spring.domain.user.model.dto.SpaceChoiceInfo; import java.util.List; diff --git a/src/main/java/space/space_spring/dao/UserDao.java b/src/main/java/space/space_spring/domain/user/repository/UserDao.java similarity index 98% rename from src/main/java/space/space_spring/dao/UserDao.java rename to src/main/java/space/space_spring/domain/user/repository/UserDao.java index 63c3b97e..503657ce 100644 --- a/src/main/java/space/space_spring/dao/UserDao.java +++ b/src/main/java/space/space_spring/domain/user/repository/UserDao.java @@ -1,4 +1,4 @@ -package space.space_spring.dao; +package space.space_spring.domain.user.repository; import jakarta.persistence.EntityManager; import jakarta.persistence.NoResultException; diff --git a/src/main/java/space/space_spring/dao/UserRepository.java b/src/main/java/space/space_spring/domain/user/repository/UserRepository.java similarity index 89% rename from src/main/java/space/space_spring/dao/UserRepository.java rename to src/main/java/space/space_spring/domain/user/repository/UserRepository.java index b4245e48..60d0dc3e 100644 --- a/src/main/java/space/space_spring/dao/UserRepository.java +++ b/src/main/java/space/space_spring/domain/user/repository/UserRepository.java @@ -1,4 +1,4 @@ -package space.space_spring.dao; +package space.space_spring.domain.user.repository; import org.springframework.data.jpa.repository.JpaRepository; import org.springframework.data.jpa.repository.Query; diff --git a/src/main/java/space/space_spring/service/UserService.java b/src/main/java/space/space_spring/domain/user/service/UserService.java similarity index 62% rename from src/main/java/space/space_spring/service/UserService.java rename to src/main/java/space/space_spring/domain/user/service/UserService.java index c6cc9124..e743db8e 100644 --- a/src/main/java/space/space_spring/service/UserService.java +++ b/src/main/java/space/space_spring/domain/user/service/UserService.java @@ -1,25 +1,19 @@ -package space.space_spring.service; +package space.space_spring.domain.user.service; import lombok.RequiredArgsConstructor; import lombok.extern.slf4j.Slf4j; import org.springframework.security.crypto.password.PasswordEncoder; import org.springframework.stereotype.Service; import org.springframework.transaction.annotation.Transactional; -import space.space_spring.dao.JwtRepository; import space.space_spring.dao.UserSpaceDao; -import space.space_spring.dto.jwt.TokenPairDTO; -import space.space_spring.dto.jwt.TokenType; -import space.space_spring.dto.user.GetUserProfileListDto; -import space.space_spring.dto.user.PostLoginDto; -import space.space_spring.dto.user.dto.SpaceChoiceViewDto; -import space.space_spring.dto.user.request.PostUserSignupRequest; -import space.space_spring.dto.user.response.GetSpaceInfoForUserResponse; -import space.space_spring.entity.TokenStorage; +import space.space_spring.domain.user.model.GetUserProfileListDto; +import space.space_spring.domain.user.model.dto.SpaceChoiceViewDto; +import space.space_spring.domain.user.model.request.PostUserSignupRequest; +import space.space_spring.domain.user.model.response.GetSpaceInfoForUserResponse; import space.space_spring.entity.UserSpace; import space.space_spring.entity.enumStatus.UserSignupType; import space.space_spring.exception.CustomException; -import space.space_spring.jwt.JwtLoginProvider; -import space.space_spring.dao.UserDao; +import space.space_spring.domain.user.repository.UserDao; import space.space_spring.entity.User; import space.space_spring.util.user.UserUtils; @@ -35,10 +29,8 @@ public class UserService { private final UserDao userDao; - private final JwtLoginProvider jwtLoginProvider; private final UserSpaceDao userSpaceDao; private final UserUtils userUtils; - private final JwtRepository jwtRepository; private final PasswordEncoder passwordEncoder; @Transactional @@ -64,45 +56,6 @@ private void validateEmailForLocalSignup(String email) { } } - @Transactional - public PostLoginDto login(PostLoginDto.Request request) { - // TODO 1. 이메일 존재 여부 확인(아이디 존재 여부 확인) - User userByEmail = userUtils.findUserByEmail(request.getEmail(), LOCAL); - log.info("userByEmail.getUserId: {}", userByEmail.getUserId()); - - // TODO 2. 비밀번호 일치 여부 확인 - validatePassword(userByEmail, request.getPassword()); - - // TODO 3. JWT 발급 -> access token, refresh token 2개 발급 - String accessToken = jwtLoginProvider.generateToken(userByEmail, TokenType.ACCESS); - String refreshToken = jwtLoginProvider.generateToken(userByEmail, TokenType.REFRESH); - - // TODO 4. refresh token db에 저장 - TokenStorage tokenStorage = TokenStorage.builder() - .user(userByEmail) - .tokenValue(refreshToken) - .build(); - jwtRepository.save(tokenStorage); - - // TODO 5. return - TokenPairDTO tokenPairDTO = TokenPairDTO.builder() - .refreshToken(refreshToken) - .accessToken(accessToken) - .build(); - - return PostLoginDto.builder() - .TokenPairDTO(tokenPairDTO) - .userId(userByEmail.getUserId()) - .build(); - } - - private void validatePassword(User userByEmail, String password) { - String encodePassword = userByEmail.getPassword(); - if(!passwordEncoder.matches(password,encodePassword)){ - throw new CustomException(PASSWORD_NO_MATCH); - } - - } @Transactional public GetSpaceInfoForUserResponse getSpaceListForUser(Long userId, int size, Long lastUserSpaceId) { diff --git a/src/main/java/space/space_spring/dto/jwt/TokenType.java b/src/main/java/space/space_spring/dto/jwt/TokenType.java deleted file mode 100644 index ec125cfe..00000000 --- a/src/main/java/space/space_spring/dto/jwt/TokenType.java +++ /dev/null @@ -1,6 +0,0 @@ -package space.space_spring.dto.jwt; - -public enum TokenType { - REFRESH, - ACCESS -} diff --git a/src/main/java/space/space_spring/interceptor/UserSpaceValidationInterceptor.java b/src/main/java/space/space_spring/interceptor/UserSpaceValidationInterceptor.java index 80031af8..8775541a 100644 --- a/src/main/java/space/space_spring/interceptor/UserSpaceValidationInterceptor.java +++ b/src/main/java/space/space_spring/interceptor/UserSpaceValidationInterceptor.java @@ -9,7 +9,7 @@ import org.springframework.web.servlet.HandlerMapping; import space.space_spring.argumentResolver.userSpace.CheckUserSpace; import space.space_spring.dao.SpaceDao; -import space.space_spring.dao.UserDao; +import space.space_spring.domain.user.repository.UserDao; import space.space_spring.dao.UserSpaceDao; import space.space_spring.entity.Space; import space.space_spring.entity.User; diff --git a/src/main/java/space/space_spring/interceptor/jwtLogin/JwtLoginAuthInterceptor.java b/src/main/java/space/space_spring/interceptor/jwtLogin/JwtLoginAuthInterceptor.java index 498bf21e..03bcfd59 100644 --- a/src/main/java/space/space_spring/interceptor/jwtLogin/JwtLoginAuthInterceptor.java +++ b/src/main/java/space/space_spring/interceptor/jwtLogin/JwtLoginAuthInterceptor.java @@ -6,13 +6,10 @@ import org.springframework.http.HttpHeaders; import org.springframework.stereotype.Component; import org.springframework.web.servlet.HandlerInterceptor; -import space.space_spring.dao.UserDao; -import space.space_spring.dto.jwt.TokenType; -import space.space_spring.exception.CustomException; +import space.space_spring.domain.authorization.jwt.model.TokenType; import space.space_spring.exception.jwt.bad_request.JwtNoTokenException; import space.space_spring.exception.jwt.bad_request.JwtUnsupportedTokenException; import space.space_spring.exception.jwt.unauthorized.JwtExpiredTokenException; -import space.space_spring.exception.jwt.unauthorized.JwtInvalidTokenException; import space.space_spring.jwt.JwtLoginProvider; import static space.space_spring.response.status.BaseExceptionResponseStatus.*; diff --git a/src/main/java/space/space_spring/interceptor/jwtSocket/JwtChannelInterceptor.java b/src/main/java/space/space_spring/interceptor/jwtSocket/JwtChannelInterceptor.java index 773c5e29..3c137e09 100644 --- a/src/main/java/space/space_spring/interceptor/jwtSocket/JwtChannelInterceptor.java +++ b/src/main/java/space/space_spring/interceptor/jwtSocket/JwtChannelInterceptor.java @@ -8,7 +8,7 @@ import org.springframework.messaging.simp.stomp.StompHeaderAccessor; import org.springframework.messaging.support.ChannelInterceptor; import org.springframework.stereotype.Component; -import space.space_spring.dto.jwt.TokenType; +import space.space_spring.domain.authorization.jwt.model.TokenType; import space.space_spring.exception.jwt.bad_request.JwtNoTokenException; import space.space_spring.exception.jwt.bad_request.JwtUnsupportedTokenException; import space.space_spring.exception.jwt.unauthorized.JwtExpiredTokenException; diff --git a/src/main/java/space/space_spring/jwt/JwtLoginProvider.java b/src/main/java/space/space_spring/jwt/JwtLoginProvider.java index 70124800..998b42c5 100644 --- a/src/main/java/space/space_spring/jwt/JwtLoginProvider.java +++ b/src/main/java/space/space_spring/jwt/JwtLoginProvider.java @@ -4,7 +4,7 @@ import lombok.extern.slf4j.Slf4j; import org.springframework.beans.factory.annotation.Value; import org.springframework.stereotype.Component; -import space.space_spring.dto.jwt.TokenType; +import space.space_spring.domain.authorization.jwt.model.TokenType; import space.space_spring.entity.User; import space.space_spring.exception.CustomException; import space.space_spring.exception.jwt.bad_request.JwtUnsupportedTokenException; diff --git a/src/main/java/space/space_spring/service/PayService.java b/src/main/java/space/space_spring/service/PayService.java index e236c87a..74b2eec6 100644 --- a/src/main/java/space/space_spring/service/PayService.java +++ b/src/main/java/space/space_spring/service/PayService.java @@ -4,7 +4,7 @@ import org.springframework.stereotype.Service; import org.springframework.transaction.annotation.Transactional; import space.space_spring.dao.PayDao; -import space.space_spring.dao.UserDao; +import space.space_spring.domain.user.repository.UserDao; import space.space_spring.dao.UserSpaceDao; import space.space_spring.dto.pay.dto.*; import space.space_spring.dto.pay.request.PostPayCreateRequest; @@ -16,10 +16,8 @@ import space.space_spring.util.user.UserUtils; import java.time.ZoneId; -import java.time.format.DateTimeFormatter; import java.util.ArrayList; import java.util.List; -import java.util.Optional; import static space.space_spring.response.status.BaseExceptionResponseStatus.USER_IS_NOT_IN_SPACE; diff --git a/src/main/java/space/space_spring/service/SpaceService.java b/src/main/java/space/space_spring/service/SpaceService.java index e4b47b77..c92f02a8 100644 --- a/src/main/java/space/space_spring/service/SpaceService.java +++ b/src/main/java/space/space_spring/service/SpaceService.java @@ -4,7 +4,7 @@ import org.springframework.stereotype.Service; import org.springframework.transaction.annotation.Transactional; import space.space_spring.dao.SpaceDao; -import space.space_spring.dao.UserDao; +import space.space_spring.domain.user.repository.UserDao; import space.space_spring.dao.UserSpaceDao; import space.space_spring.dto.space.GetSpaceHomeDto; import space.space_spring.dto.space.GetSpaceJoinDto; @@ -22,7 +22,6 @@ import space.space_spring.util.userSpace.UserSpaceUtils; import java.time.ZoneId; -import java.time.format.DateTimeFormatter; import java.util.Optional; import static space.space_spring.response.status.BaseExceptionResponseStatus.USER_IS_NOT_IN_SPACE; diff --git a/src/main/java/space/space_spring/service/VoiceRoomService.java b/src/main/java/space/space_spring/service/VoiceRoomService.java index 7c9b709f..c831ef89 100644 --- a/src/main/java/space/space_spring/service/VoiceRoomService.java +++ b/src/main/java/space/space_spring/service/VoiceRoomService.java @@ -5,7 +5,7 @@ import org.springframework.beans.factory.annotation.Autowired; import org.springframework.core.task.TaskExecutor; import org.springframework.stereotype.Service; -import space.space_spring.dao.UserDao; +import space.space_spring.domain.user.repository.UserDao; import space.space_spring.dao.UserSpaceDao; import space.space_spring.dao.VoiceRoomDao; import space.space_spring.dao.VoiceRoomRepository; @@ -13,20 +13,15 @@ import space.space_spring.entity.Space; import space.space_spring.entity.User; import space.space_spring.entity.VoiceRoom; -import space.space_spring.exception.CustomException; import space.space_spring.util.LiveKitUtils; import space.space_spring.util.space.SpaceUtils; -import space.space_spring.util.user.UserUtils; import java.util.Collections; import java.util.List; -import java.util.Optional; import java.util.concurrent.CompletableFuture; import java.util.function.Function; import java.util.stream.Collectors; -import static space.space_spring.response.status.BaseExceptionResponseStatus.USER_IS_NOT_IN_SPACE; - @Service @RequiredArgsConstructor public class VoiceRoomService { diff --git a/src/main/java/space/space_spring/util/user/UserUtils.java b/src/main/java/space/space_spring/util/user/UserUtils.java index e4333292..7414eabd 100644 --- a/src/main/java/space/space_spring/util/user/UserUtils.java +++ b/src/main/java/space/space_spring/util/user/UserUtils.java @@ -3,7 +3,7 @@ import lombok.RequiredArgsConstructor; import org.springframework.stereotype.Component; import org.springframework.transaction.annotation.Transactional; -import space.space_spring.dao.UserDao; +import space.space_spring.domain.user.repository.UserDao; import space.space_spring.entity.User; import space.space_spring.entity.enumStatus.UserSignupType; import space.space_spring.exception.CustomException; diff --git a/src/main/java/space/space_spring/util/userSpace/MemoryUserSpaceUtils.java b/src/main/java/space/space_spring/util/userSpace/MemoryUserSpaceUtils.java index a7f34c0e..80b06393 100644 --- a/src/main/java/space/space_spring/util/userSpace/MemoryUserSpaceUtils.java +++ b/src/main/java/space/space_spring/util/userSpace/MemoryUserSpaceUtils.java @@ -4,7 +4,7 @@ import org.springframework.stereotype.Component; import org.springframework.transaction.annotation.Transactional; import space.space_spring.dao.SpaceDao; -import space.space_spring.dao.UserDao; +import space.space_spring.domain.user.repository.UserDao; import space.space_spring.dao.UserSpaceDao; import space.space_spring.entity.Space; import space.space_spring.entity.User;