diff --git a/docker-test-server/build.gradle b/docker-test-server/build.gradle index c38485e..5436eb8 100644 --- a/docker-test-server/build.gradle +++ b/docker-test-server/build.gradle @@ -22,17 +22,16 @@ repositories { } dependencies { + implementation 'org.springframework.boot:spring-boot-starter-validation' + implementation 'com.auth0:java-jwt:3.18.1' implementation 'io.github.cdimascio:java-dotenv:+' - implementation 'io.jsonwebtoken:jjwt-api:0.11.5' - implementation 'org.json:json:20171018' + implementation 'org.json:json:20171018' implementation 'org.springframework.boot:spring-boot-starter-data-jpa' implementation 'org.springframework.boot:spring-boot-starter-web' implementation 'io.springfox:springfox-boot-starter:3.0.0' compileOnly 'org.projectlombok:lombok' developmentOnly 'org.springframework.boot:spring-boot-devtools' runtimeOnly 'com.mysql:mysql-connector-j' - runtimeOnly 'io.jsonwebtoken:jjwt-impl:0.11.5' - runtimeOnly 'io.jsonwebtoken:jjwt-jackson:0.11.5' annotationProcessor 'org.projectlombok:lombok' testImplementation 'org.springframework.boot:spring-boot-starter-test' runtimeOnly 'com.h2database:h2' diff --git a/docker-test-server/run.sh b/docker-test-server/run.sh new file mode 100755 index 0000000..ecb4677 --- /dev/null +++ b/docker-test-server/run.sh @@ -0,0 +1,5 @@ +#!/bin/bash + +docker-compose down +docker rmi docker-test-server-server:latest +docker-compose up -d \ No newline at end of file diff --git a/docker-test-server/sql/init.sql b/docker-test-server/sql/init.sql index c2f588b..a6ff12e 100644 --- a/docker-test-server/sql/init.sql +++ b/docker-test-server/sql/init.sql @@ -2,12 +2,8 @@ CREATE DATABASE IF NOT EXISTS toothFairy; USE toothFairy; CREATE TABLE user_tb ( - email VARCHAR(255) PRIMARY KEY, - pet_name VARCHAR(50), - pet_weight INT, - access_token VARCHAR(255), - refresh_token VARCHAR(255) -) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci; - -INSERT INTO user_tb (email, pet_name, pet_weight, access_token, refresh_token) -VALUES ('test@gmail.com', 'Charlie', 12, 'test_access_token', 'test_refresh_token'); \ No newline at end of file + id BIGINT PRIMARY KEY, + pet_name VARCHAR(50) NOT NULL, + pet_weight INT NOT NULL, + random_id VARCHAR(255) NOT NULL +) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci; \ No newline at end of file diff --git a/docker-test-server/src/main/java/com/example/server/controller/HomeController.java b/docker-test-server/src/main/java/com/example/server/controller/HomeController.java index 37077a6..5ca6041 100644 --- a/docker-test-server/src/main/java/com/example/server/controller/HomeController.java +++ b/docker-test-server/src/main/java/com/example/server/controller/HomeController.java @@ -8,7 +8,10 @@ import org.springframework.web.bind.annotation.RequestMapping; import org.springframework.web.bind.annotation.RestController; +import com.example.server.error.CErrorResponse; import com.example.server.error.CException; +import com.example.server.error.ErrorCode; +import com.example.server.jwt.JwtTokenService; import com.example.server.model.User; import com.example.server.model.UserPet; import com.example.server.service.HomeService; @@ -22,7 +25,7 @@ public class HomeController { private final InvalidTokenService invalidTokenService; private final HomeService homeService; - + private final JwtTokenService jwtTokenService; // 홈페이지 // 펫이름 가져오기 // Input : 파라미터 AccessToken @@ -32,23 +35,46 @@ public class HomeController { // Output(500) : 서버에러 @GetMapping("") public ResponseEntity home(@RequestHeader("AccessToken") String AccessToken) { + // 1. RefreshToken Valid? + try { + if(jwtTokenService.validateAccessToken(AccessToken) == false) { + throw new CException(ErrorCode.INVALID_TOKEN); + } + + } catch (Exception e) { + throw new CException(ErrorCode.INVALID_TOKEN); + } + + // 2. Check userId + Long userId; + try { + userId = jwtTokenService.extractIdFromAccessToken(AccessToken); + if(invalidTokenService.existsById(userId) == false) { + throw new CException(ErrorCode.INVALID_TOKEN); + } + } catch (Exception e) { + throw new CException(ErrorCode.INVALID_TOKEN); + } + + // 3. Get Pet Information By UserId User user = null; try { - invalidTokenService.isTokenInvalid(AccessToken); - System.out.println(AccessToken); - user = homeService.getPetInformation(AccessToken); - } catch (CException e) { - return ResponseEntity.status(e.getErrorCode().getStatus()).body(e.getErrorCode().getMessage()); + user = homeService.getPetInformation(userId); } catch (Exception e) { - return ResponseEntity.status(500).body(e.toString()); + throw new CException(ErrorCode.INTERNAL_SERVER_ERROR); } if(Objects.isNull(user)) - return ResponseEntity.status(500).body("유저 정보를 가져오지 못 했습니다."); + throw new CException(ErrorCode.INTERNAL_SERVER_ERROR); UserPet userPet = new UserPet(user.getPetName(), user.getPetWeight()); - // access 토큰 확인 - return ResponseEntity.status(200).body(userPet); + return ResponseEntity + .status(ErrorCode.SUCCESS.getStatus()) + .body(CErrorResponse.builder() + .status(ErrorCode.SUCCESS.getStatus()) + .message(userPet) + .build() + ); } -} +} \ No newline at end of file diff --git a/docker-test-server/src/main/java/com/example/server/controller/LoginController.java b/docker-test-server/src/main/java/com/example/server/controller/LoginController.java index ff931f3..30d551d 100644 --- a/docker-test-server/src/main/java/com/example/server/controller/LoginController.java +++ b/docker-test-server/src/main/java/com/example/server/controller/LoginController.java @@ -6,7 +6,11 @@ import org.springframework.web.bind.annotation.RequestMapping; import org.springframework.web.bind.annotation.RestController; +import com.example.server.error.CErrorResponse; import com.example.server.error.CException; +import com.example.server.error.ErrorCode; +import com.example.server.jwt.JwtTokenService; +import com.example.server.model.Token; import com.example.server.service.LoginService; import lombok.RequiredArgsConstructor; @@ -16,27 +20,60 @@ @RequestMapping("/api/login") public class LoginController { private final LoginService loginService; + private final JwtTokenService jwtTokenService; - // 로그인시 재가입 여부를 판단하는 API - // Input : AccessToken, RefreshToken, ExpiresIn, RefreshTokenExpiresIn - // Output(403) : 이미 가입한 사용자 -> 데이터 Update -> 홈페이지 - // Output(401) : 유효하지 않은 토큰 - // Output(200) : 재가입 No -> 회원가입 페이지 + // 로그인시 회원가입, 재로그인을 판단하는 API + // Input : AccessToken(Kakao Access Token) + // Output(403) : 존재하지 않는 유저(회원가입) : Message "존재하지 않는 유저" + // Output(401) : 유효하지 않은 토큰(에러) : Message "유효하지 않은 '소셜' 액세스 토큰" + // Output(200) : 가입 유저(재로그인) @GetMapping("") - public ResponseEntity login( - @RequestHeader("AccessToken") String AccessToken, - @RequestHeader("ExpiresIn") Integer ExpiresIn, - @RequestHeader("RefreshToken") String RefreshToken, - @RequestHeader("RefreshTokenExpiresIn") Integer RefreshTokenExpiresIn - ){ + public ResponseEntity login (@RequestHeader("AccessToken") String AccessToken) { + Long userId = Long.valueOf(0); + // 1. KAKAO OPEN API로 userId 확인. + // => Error : 유효하지 않는 토큰(에러) try { - loginService.isUserRejoin(AccessToken, ExpiresIn, RefreshToken, RefreshTokenExpiresIn); - } catch (CException e) { - return ResponseEntity.status(e.getErrorCode().getStatus()).body(e.getErrorCode().getMessage()); - } catch (Exception e) { - return ResponseEntity.status(500).body(e.toString()); + userId = loginService.getUserIdByKakaoOpenApi(AccessToken); + } catch(Exception e) { + throw new CException(ErrorCode.KAKAO_INVALID_TOKEN); } - - return ResponseEntity.status(200).body("."); + // 2. userId로 데이터베이스 확인 + // => 데이터베이스 false : 존재하지 않는 유저(회원가입) + try { + System.out.println(loginService.getUserIdByDatabase(userId)); + if(loginService.getUserIdByDatabase(userId) == false) { + throw new CException(ErrorCode.GHOST_USER); + } + } catch(Exception e) { + System.out.println("Here"); + throw new CException(ErrorCode.GHOST_USER); + } + + // 3. JWT AccessToken, RefreshToken 토큰 발급 + Token token = new Token(); + String randomId = jwtTokenService.generateRandomId(); + try { + String accessToken = jwtTokenService.createAccessToken(userId); + String refreshToken = jwtTokenService.createRefreshToken(userId, randomId); + token.setAccessToken(accessToken); + token.setRefreshToken(refreshToken); + } catch(Exception e) { + throw new CException(ErrorCode.INTERNAL_SERVER_ERROR); + } + + // 4. RefreshToken RandomID Database에 저장 + try { + loginService.updateRandomIdByUserId(userId, randomId); + } catch(Exception e) { + throw new CException(ErrorCode.KAKAO_INVALID_TOKEN); + } + + return ResponseEntity + .status(ErrorCode.SUCCESS.getStatus()) + .body(CErrorResponse.builder() + .status(ErrorCode.SUCCESS.getStatus()) + .message(token) + .build() + ); } } diff --git a/docker-test-server/src/main/java/com/example/server/controller/RefreshTokenController.java b/docker-test-server/src/main/java/com/example/server/controller/RefreshTokenController.java new file mode 100644 index 0000000..19fe0ae --- /dev/null +++ b/docker-test-server/src/main/java/com/example/server/controller/RefreshTokenController.java @@ -0,0 +1,86 @@ +package com.example.server.controller; + +import org.springframework.http.ResponseEntity; +import org.springframework.web.bind.annotation.GetMapping; +import org.springframework.web.bind.annotation.RequestHeader; +import org.springframework.web.bind.annotation.RequestMapping; +import org.springframework.web.bind.annotation.RestController; + +import com.example.server.error.CErrorResponse; +import com.example.server.error.CException; +import com.example.server.error.ErrorCode; +import com.example.server.jwt.JwtTokenService; +import com.example.server.model.Token; +import com.example.server.service.RefreshTokenService; + +import lombok.RequiredArgsConstructor; + +@RestController +@RequiredArgsConstructor +@RequestMapping("/api/refresh") +public class RefreshTokenController { + private final RefreshTokenService refreshTokenService; + private final JwtTokenService jwtTokenService; + + // RefreshToken으로 AccessToken과 RefreshToken 새로 발급 + @GetMapping("") + public ResponseEntity refreshAccessToken (@RequestHeader("RefreshToken") String RefreshToken) { + // 1. RefreshToken Valid? + try { + if(jwtTokenService.validateRefreshToken(RefreshToken) == false) { + throw new CException(ErrorCode.INVALID_TOKEN); + } + } catch (Exception e) { + throw new CException(ErrorCode.INVALID_TOKEN); + } + + // 2. Get userId & radomId from RefreshToken + Long userId = null; + String randomId = null; + try { + userId = jwtTokenService.extractIdFromRefreshToken(RefreshToken); + randomId = jwtTokenService.extractRandomIdFromRefreshToken(RefreshToken); + } catch (Exception e) { + throw new CException(ErrorCode.INVALID_TOKEN); + } + + if(userId == null || randomId == null) + throw new CException(ErrorCode.INVALID_TOKEN); + + // 3. Check userId & radomId + try { + if(refreshTokenService.checkIdAndRandomId(userId, randomId) == false) { + throw new CException(ErrorCode.INVALID_TOKEN); + } + } catch (Exception e) { + throw new CException(ErrorCode.INVALID_TOKEN); + } + + // 4. JWT AccessToken, RefreshToken 토큰 발급 + Token token = new Token(); + String new_randomId = jwtTokenService.generateRandomId(); + try { + String accessToken = jwtTokenService.createAccessToken(userId); + String refreshToken = jwtTokenService.createRefreshToken(userId, new_randomId); + token.setAccessToken(accessToken); + token.setRefreshToken(refreshToken); + } catch(Exception e) { + throw new CException(ErrorCode.INTERNAL_SERVER_ERROR); + } + + // 5. RefreshToken RandomID Database에 수정 + try { + refreshTokenService.updateRandomIdByUserId(userId, new_randomId); + } catch(Exception e) { + throw new CException(ErrorCode.INTERNAL_SERVER_ERROR); + } + + return ResponseEntity + .status(ErrorCode.SUCCESS.getStatus()) + .body(CErrorResponse.builder() + .status(ErrorCode.SUCCESS.getStatus()) + .message(token) + .build() + ); + } +} diff --git a/docker-test-server/src/main/java/com/example/server/controller/RegisterController.java b/docker-test-server/src/main/java/com/example/server/controller/RegisterController.java index 1a04577..6863f6c 100644 --- a/docker-test-server/src/main/java/com/example/server/controller/RegisterController.java +++ b/docker-test-server/src/main/java/com/example/server/controller/RegisterController.java @@ -1,12 +1,21 @@ package com.example.server.controller; +import javax.validation.Valid; + import org.springframework.http.ResponseEntity; import org.springframework.web.bind.annotation.PostMapping; +import org.springframework.web.bind.annotation.RequestBody; import org.springframework.web.bind.annotation.RequestHeader; + import org.springframework.web.bind.annotation.RequestMapping; import org.springframework.web.bind.annotation.RestController; +import com.example.server.error.CErrorResponse; import com.example.server.error.CException; +import com.example.server.error.ErrorCode; +import com.example.server.jwt.JwtTokenService; +import com.example.server.model.Token; +import com.example.server.model.UserPet; import com.example.server.service.RegisterService; import lombok.RequiredArgsConstructor; @@ -16,27 +25,60 @@ @RequestMapping("/api/register") public class RegisterController { private final RegisterService registerService; + private final JwtTokenService jwtTokenService; // 회원가입이 끝나면 저장하기 위한 API - // Input : AccessToken, ExpiresI, RefreshToken, RefreshTokenExpiresIn, PetName, PetWeight + // Input : AccessToken, PetName, PetWeight // Output : status(200, 401, 500) @PostMapping("") public ResponseEntity register( @RequestHeader("AccessToken") String AccessToken, - @RequestHeader("ExpiresIn") Integer ExpiresIn, - @RequestHeader("RefreshToken") String RefreshToken, - @RequestHeader("RefreshTokenExpiresIn") Integer RefreshTokenExpiresIn, - @RequestHeader("PetName") String PetName, - @RequestHeader("PetWeight") Integer PetWeight + @Valid @RequestBody UserPet userPet ) { + Long userId = Long.valueOf(0); + // 1. KAKAO OPEN API로 userId 확인. + // => Error : 유효하지 않는 토큰(에러) + try { + userId = registerService.getUserIdByKakaoOpenApi(AccessToken); + } catch(Exception e) { + throw new CException(ErrorCode.KAKAO_INVALID_TOKEN); + } + + // 2. userId로 데이터베이스 확인 + // => 데이터베이스 true : 이미 존재하는 유저(Bad Request 400) + try { + if(registerService.getUserIdByDatabase(userId) == true) { + throw new CException(ErrorCode.REGISTERED_USER); + } + } catch(Exception e) { + throw new CException(ErrorCode.REGISTERED_USER); + } + + // 3. JWT AccessToken, RefreshToken 토큰 발급 + Token token = new Token(); + String randomId = jwtTokenService.generateRandomId(); + try { + String accessToken = jwtTokenService.createAccessToken(userId); + String refreshToken = jwtTokenService.createRefreshToken(userId, randomId); + token.setAccessToken(accessToken); + token.setRefreshToken(refreshToken); + } catch(Exception e) { + throw new CException(ErrorCode.INTERNAL_SERVER_ERROR); + } + + // 4. 모든 정보 저장. try { - registerService.isUserRejoin(AccessToken, ExpiresIn, RefreshToken, RefreshTokenExpiresIn, PetName, PetWeight); - } catch (CException e) { - return ResponseEntity.status(e.getErrorCode().getStatus()).body(e.getErrorCode().getMessage()); - } catch (Exception e) { - return ResponseEntity.status(500).body(e.toString()); + registerService.createUserInfo(userId, randomId, userPet.getPetName(), userPet.getPetWeight());; + } catch(Exception e) { + throw new CException(ErrorCode.INTERNAL_SERVER_ERROR); } - return ResponseEntity.status(200).body("."); + return ResponseEntity + .status(ErrorCode.SUCCESS.getStatus()) + .body(CErrorResponse.builder() + .status(ErrorCode.SUCCESS.getStatus()) + .message(token) + .build() + ); } } diff --git a/docker-test-server/src/main/java/com/example/server/controller/TartarController.java b/docker-test-server/src/main/java/com/example/server/controller/TartarController.java deleted file mode 100644 index 86fdbbc..0000000 --- a/docker-test-server/src/main/java/com/example/server/controller/TartarController.java +++ /dev/null @@ -1,36 +0,0 @@ -package com.example.server.controller; - -import org.springframework.http.ResponseEntity; -import org.springframework.web.bind.annotation.GetMapping; -import org.springframework.web.bind.annotation.RequestHeader; -import org.springframework.web.bind.annotation.RequestMapping; -import org.springframework.web.bind.annotation.RestController; - -import com.example.server.error.CException; -import com.example.server.service.InvalidTokenService; - -import lombok.RequiredArgsConstructor; - -@RestController -@RequiredArgsConstructor -@RequestMapping("/api/tartar") -public class TartarController { - private final InvalidTokenService invalidTokenService; - - // Default : - // 1. Token이 유효한지 확인. - - // 사용자가 애완견 이빨을 찍으면 - @GetMapping("") - public ResponseEntity tartar(@RequestHeader("AccessToken") String AccessToken) { - try { - invalidTokenService.isTokenInvalid(AccessToken); - } catch (CException e) { - ResponseEntity.status(e.getErrorCode().getStatus()).body(e.getErrorCode().getMessage()); - } catch (Exception e) { - ResponseEntity.status(500).body(e.toString()); - } - - return ResponseEntity.status(200).body("null"); - } -} diff --git a/docker-test-server/src/main/java/com/example/server/controller/ToothController.java b/docker-test-server/src/main/java/com/example/server/controller/ToothController.java index 383b2dd..088c67f 100644 --- a/docker-test-server/src/main/java/com/example/server/controller/ToothController.java +++ b/docker-test-server/src/main/java/com/example/server/controller/ToothController.java @@ -1,12 +1,15 @@ package com.example.server.controller; import org.springframework.http.ResponseEntity; -import org.springframework.web.bind.annotation.PutMapping; +import org.springframework.web.bind.annotation.GetMapping; import org.springframework.web.bind.annotation.RequestHeader; import org.springframework.web.bind.annotation.RequestMapping; import org.springframework.web.bind.annotation.RestController; +import com.example.server.error.CErrorResponse; import com.example.server.error.CException; +import com.example.server.error.ErrorCode; +import com.example.server.jwt.JwtTokenService; import com.example.server.service.InvalidTokenService; import lombok.RequiredArgsConstructor; @@ -15,22 +18,40 @@ @RequiredArgsConstructor @RequestMapping("/api/tooth") public class ToothController { - // 양치질이 끝나면 또는 주기적으로 Front에서 데이터를 보내면 - // TimeStream에 저장해주는 역할 API. - + private final JwtTokenService jwtTokenService; private final InvalidTokenService invalidTokenService; - // 사용자가 애완견 이빨을 찍으면 - @PutMapping("") - public ResponseEntity tooth(@RequestHeader("AccessToken") String AccessToken) { + @GetMapping("") + public ResponseEntity mypageGetinfo(@RequestHeader("AccessToken") String AccessToken) { + // 1. RefreshToken Valid? + try { + if(jwtTokenService.validateAccessToken(AccessToken) == false) { + throw new CException(ErrorCode.INVALID_TOKEN); + } + } catch (Exception e) { + throw new CException(ErrorCode.INVALID_TOKEN); + } + + // 2. Check userId + Long userId; try { - invalidTokenService.isTokenInvalid(AccessToken); - } catch (CException e) { - ResponseEntity.status(e.getErrorCode().getStatus()).body(e.getErrorCode().getMessage()); + userId = jwtTokenService.extractIdFromAccessToken(AccessToken); + if(invalidTokenService.existsById(userId) == false) { + throw new CException(ErrorCode.INVALID_TOKEN); + } } catch (Exception e) { - ResponseEntity.status(500).body(e.toString()); + throw new CException(ErrorCode.INVALID_TOKEN); } + + // 3. Create New Data + - return ResponseEntity.status(200).body("null"); + return ResponseEntity + .status(ErrorCode.SUCCESS.getStatus()) + .body(CErrorResponse.builder() + .status(ErrorCode.SUCCESS.getStatus()) + .message(".") + .build() + ); } } diff --git a/docker-test-server/src/main/java/com/example/server/controller/UpdateAccessController.java b/docker-test-server/src/main/java/com/example/server/controller/UpdateAccessController.java deleted file mode 100644 index 8aa3ab6..0000000 --- a/docker-test-server/src/main/java/com/example/server/controller/UpdateAccessController.java +++ /dev/null @@ -1,34 +0,0 @@ -package com.example.server.controller; - -import org.springframework.http.ResponseEntity; -import org.springframework.web.bind.annotation.PatchMapping; -import org.springframework.web.bind.annotation.RequestHeader; -import org.springframework.web.bind.annotation.RequestMapping; -import org.springframework.web.bind.annotation.RestController; - -import com.example.server.error.CException; -import com.example.server.service.UpdateAccessService; - -import lombok.RequiredArgsConstructor; - -@RestController // REST API 컨트롤러 선언, @Controller + @ResponseBody 결합 -@RequiredArgsConstructor // final 필드의 생성자 자동 생성 -@RequestMapping("/api/update") -public class UpdateAccessController { - private UpdateAccessService updateAccessService; - - // AccessToken을 새로 발급 받았을때 사용하는 API. - // 서버에 새로운 AccessToken을 제공. - @PatchMapping("/accesstoken") - public ResponseEntity updateAccessToken(@RequestHeader("AccessToken") String AccessToken, - @RequestHeader("ExpiresIn") Integer ExpiresIn) { - try { - updateAccessService.updateAccessTokenById(AccessToken, ExpiresIn); - } catch(CException e) { - ResponseEntity.status(e.getErrorCode().getStatus()).body(e.getErrorCode().getMessage()); - } catch(Exception e) { - ResponseEntity.status(500).body(e.toString()); - } - return ResponseEntity.status(null).body(null); - } -} diff --git a/docker-test-server/src/main/java/com/example/server/controller/UserController.java b/docker-test-server/src/main/java/com/example/server/controller/UserController.java index 4c93baa..de79330 100644 --- a/docker-test-server/src/main/java/com/example/server/controller/UserController.java +++ b/docker-test-server/src/main/java/com/example/server/controller/UserController.java @@ -9,7 +9,10 @@ import org.springframework.web.bind.annotation.RequestMapping; import org.springframework.web.bind.annotation.RestController; +import com.example.server.error.CErrorResponse; import com.example.server.error.CException; +import com.example.server.error.ErrorCode; +import com.example.server.jwt.JwtTokenService; import com.example.server.model.User; import com.example.server.model.UserPet; import com.example.server.service.InvalidTokenService; @@ -21,8 +24,9 @@ @RequiredArgsConstructor @RequestMapping("/api/user") public class UserController { - private InvalidTokenService invalidTokenService; - private UserService userService; + private final InvalidTokenService invalidTokenService; + private final UserService userService; + private final JwtTokenService jwtTokenService; @GetMapping("test") public ResponseEntity test() { @@ -32,25 +36,49 @@ public ResponseEntity test() { // 마이페이지 // 마이페이지를 보여주는 API // Input : AccessToken - // Output : User + // Output : User status(200, 401, 500) @GetMapping("/getinfo") public ResponseEntity mypageGetinfo(@RequestHeader("AccessToken") String AccessToken) { + // 1. RefreshToken Valid? + try { + if(jwtTokenService.validateAccessToken(AccessToken) == false) { + throw new CException(ErrorCode.INVALID_TOKEN); + } + } catch (Exception e) { + throw new CException(ErrorCode.INVALID_TOKEN); + } + + // 2. Check userId + Long userId; + try { + userId = jwtTokenService.extractIdFromAccessToken(AccessToken); + if(invalidTokenService.existsById(userId) == false) { + throw new CException(ErrorCode.INVALID_TOKEN); + } + } catch (Exception e) { + throw new CException(ErrorCode.INVALID_TOKEN); + } + + // 3. Get Pet Information By UserId User user = null; try { - invalidTokenService.isTokenInvalid(AccessToken); - user = userService.getPetInformation(AccessToken); - } catch (CException e) { - ResponseEntity.status(e.getErrorCode().getStatus()).body(e.getErrorCode().getMessage()); + user = userService.getPetInformation(userId); } catch (Exception e) { - ResponseEntity.status(500).body(e.toString()); + throw new CException(ErrorCode.INTERNAL_SERVER_ERROR); } if(Objects.isNull(user)) - ResponseEntity.status(500).body("유저 정보를 가져오지 못 했습니다."); - - UserPet userPet = new UserPet(user.getPetName(), user.getPetWeight()); + throw new CException(ErrorCode.INTERNAL_SERVER_ERROR); - return ResponseEntity.status(200).body(userPet); + UserPet userPet = new UserPet(user.getPetName(), user.getPetWeight()); + + return ResponseEntity + .status(ErrorCode.SUCCESS.getStatus()) + .body(CErrorResponse.builder() + .status(ErrorCode.SUCCESS.getStatus()) + .message(userPet) + .build() + ); } // 마이페이지 수정 @@ -63,15 +91,38 @@ public ResponseEntity mypageGetinfo( @RequestHeader("PetName") String PetName, @RequestHeader("PetWeight") Integer PetWeight ) { + // 1. RefreshToken Valid? try { - invalidTokenService.isTokenInvalid(AccessToken); - userService.setPetInformation(AccessToken, PetName, PetWeight); - } catch (CException e) { - ResponseEntity.status(e.getErrorCode().getStatus()).body(e.getErrorCode().getMessage()); + if(jwtTokenService.validateAccessToken(AccessToken) == false) { + throw new CException(ErrorCode.INVALID_TOKEN); + } } catch (Exception e) { - ResponseEntity.status(500).body(e.toString()); + throw new CException(ErrorCode.INVALID_TOKEN); } - return ResponseEntity.ok().body("."); + // 2. Check userId + Long userId; + try { + userId = jwtTokenService.extractIdFromAccessToken(AccessToken); + if(invalidTokenService.existsById(userId) == false) { + throw new CException(ErrorCode.INVALID_TOKEN); + } + } catch (Exception e) { + throw new CException(ErrorCode.INVALID_TOKEN); + } + + try { + userService.setPetInformation(userId, PetName, PetWeight); + } catch (Exception e) { + throw new CException(ErrorCode.INTERNAL_SERVER_ERROR); + } + + return ResponseEntity + .status(ErrorCode.SUCCESS.getStatus()) + .body(CErrorResponse.builder() + .status(ErrorCode.SUCCESS.getStatus()) + .message(".") + .build() + ); } } \ No newline at end of file diff --git a/docker-test-server/src/main/java/com/example/server/error/CErrorResponse.java b/docker-test-server/src/main/java/com/example/server/error/CErrorResponse.java new file mode 100644 index 0000000..c1fbb84 --- /dev/null +++ b/docker-test-server/src/main/java/com/example/server/error/CErrorResponse.java @@ -0,0 +1,23 @@ +package com.example.server.error; + +import org.springframework.http.ResponseEntity; + +import lombok.Builder; +import lombok.Getter; + +@Getter +@Builder +public class CErrorResponse { + private final int status; + private final Object message; + + public static ResponseEntity toResponseEntity(ErrorCode errorCode) { + return ResponseEntity + .status(errorCode.getStatus()) + .body(CErrorResponse.builder() + .status(errorCode.getStatus()) + .message(errorCode.getMessage()) + .build() + ); + } +} diff --git a/docker-test-server/src/main/java/com/example/server/error/CException.java b/docker-test-server/src/main/java/com/example/server/error/CException.java index 6d22e7f..479e4ef 100644 --- a/docker-test-server/src/main/java/com/example/server/error/CException.java +++ b/docker-test-server/src/main/java/com/example/server/error/CException.java @@ -10,9 +10,4 @@ public CException(ErrorCode errorCode) { super(errorCode.getMessage()); this.errorCode = errorCode; } - - public CException(ErrorCode errorCode, String message) { - super(message); - this.errorCode = errorCode; - } } diff --git a/docker-test-server/src/main/java/com/example/server/error/CExceptionHandler.java b/docker-test-server/src/main/java/com/example/server/error/CExceptionHandler.java new file mode 100644 index 0000000..a883f2b --- /dev/null +++ b/docker-test-server/src/main/java/com/example/server/error/CExceptionHandler.java @@ -0,0 +1,39 @@ +package com.example.server.error; + +import org.springframework.http.HttpStatus; +import org.springframework.http.ResponseEntity; +import org.springframework.web.bind.annotation.ExceptionHandler; +import org.springframework.web.bind.annotation.RestControllerAdvice; + +import lombok.extern.slf4j.Slf4j; + +@Slf4j +@RestControllerAdvice +public class CExceptionHandler { + @ExceptionHandler(CException.class) + protected ResponseEntity handleCustomException(CException e) { + log.error("CustomException: {}", e.getErrorCode()); + return CErrorResponse.toResponseEntity(e.getErrorCode()); + } + + // Null 값 처리 + @ExceptionHandler(NullPointerException.class) + public ResponseEntity handleNullPointerException( + NullPointerException ex) { + + CErrorResponse response = CErrorResponse.builder() + .status(HttpStatus.BAD_REQUEST.value()) + .message("Required value is null") + .build(); + + return ResponseEntity + .status(HttpStatus.BAD_REQUEST) + .body(response); + } + + @ExceptionHandler(Exception.class) + protected ResponseEntity handleException(Exception e) { + log.error("HandleException: {}", e.getMessage()); + return CErrorResponse.toResponseEntity(ErrorCode.INTERNAL_SERVER_ERROR); + } +} diff --git a/docker-test-server/src/main/java/com/example/server/error/ErrorCode.java b/docker-test-server/src/main/java/com/example/server/error/ErrorCode.java index 92af3c4..c89f3a8 100644 --- a/docker-test-server/src/main/java/com/example/server/error/ErrorCode.java +++ b/docker-test-server/src/main/java/com/example/server/error/ErrorCode.java @@ -6,12 +6,18 @@ @Getter @AllArgsConstructor public enum ErrorCode { - SUCCESS(0, "성공"), - INVALID_TOKEN(401, "유효하지 않은 토큰입니다."), - REESSUIE_TOKEN(402, "토큰을 재발급 받아야합니다."), - ALREADY_REGISTER_USER(403, "이미 가입한 유저입니다."), - INTERNAL_SERVER_ERROR(500, "서버 오류가 발생했습니다."), - DATABASE_ERROR(501, "데이터베이스 오류가 발생했습니다"); + // 200 + SUCCESS(200, "."), + + // 400 에러 + REGISTERED_USER(400, "이미 존재하는 유저"), + NULL_VALUE(400, "필수 변수에 NULL값 존재"), + KAKAO_INVALID_TOKEN(401, "유효하지 않은 '소셜' 액세스 토큰"), + INVALID_TOKEN(401, "유효하지 않은 토큰"), + GHOST_USER(403, "존재하는 않는 유저"), + + // 500 에러 + INTERNAL_SERVER_ERROR(500, "서버 오류가 발생했습니다."); private final int status; private final String message; diff --git a/docker-test-server/src/main/java/com/example/server/jwt/JwtTokenService.java b/docker-test-server/src/main/java/com/example/server/jwt/JwtTokenService.java new file mode 100644 index 0000000..dd4ac51 --- /dev/null +++ b/docker-test-server/src/main/java/com/example/server/jwt/JwtTokenService.java @@ -0,0 +1,130 @@ +package com.example.server.jwt; + +import java.security.SecureRandom; +import java.util.Date; + +import org.springframework.stereotype.Service; + +import com.auth0.jwt.JWT; +import com.auth0.jwt.algorithms.Algorithm; +import com.auth0.jwt.interfaces.DecodedJWT; + +import lombok.extern.slf4j.Slf4j; + +@Slf4j +@Service +public class JwtTokenService { + + private String secret = "hjkdasfh;jnkladfsjkl;dasfnkl;asdfjkl;asdfjkl;"; + + private int accessTokenExpMinutes = 600 * 1000; // 10분 + + private int refreshTokenExpMinutes = 1209600 * 1000; // 2주 + + private final Algorithm algorithm = Algorithm.HMAC256(secret); + + public String generateRandomId() { + SecureRandom random = new SecureRandom(); + StringBuilder sb = new StringBuilder(64); + String characters = "0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz"; + + for (int i = 0; i < 64; i++) { + int randomIndex = random.nextInt(characters.length()); + sb.append(characters.charAt(randomIndex)); + } + + return sb.toString(); + } + + // AccessToken 생성 + public String createAccessToken(Long id) { + Date now = new Date(); + Date validity = new Date(now.getTime() + accessTokenExpMinutes); + + String createdToken = JWT.create() + .withSubject(String.valueOf(id)) + .withExpiresAt(validity) + .sign(algorithm); + + return createdToken; + } + + // RefreshToken 생성 + public String createRefreshToken(Long id, String randomId) { + String ramdomId = randomId; + + Date now = new Date(); + Date validity = new Date(now.getTime() + refreshTokenExpMinutes); + + String createdToken = JWT.create() + .withSubject(String.valueOf(id)) + .withClaim("RandomId", ramdomId) // Kakao AccessToken + .withExpiresAt(validity) + .sign(algorithm); + + return createdToken; + } + + // AccessToken Validation + public boolean validateAccessToken(String token) throws Exception { + // 1. Verify AccessToken + DecodedJWT jwt = JWT.require(algorithm) + .build() + .verify(token); + + // 2. Check Expired AccessToken + Date expiresAt = jwt.getExpiresAt(); + System.out.println((new Date())); + System.out.println(expiresAt); + if (expiresAt != null && expiresAt.before(new Date())) { + log.error("만료된 토큰입니다."); + return false; + } + return true; + } + + // RefreshToken Validation + public boolean validateRefreshToken(String token) throws Exception { + // 1. Verify RefreshToken + DecodedJWT jwt = JWT.require(algorithm) + .build() + .verify(token); + + // 2. Check Expired RefreshToken + Date expiresAt = jwt.getExpiresAt(); + if (expiresAt != null && expiresAt.before(new Date())) { + log.error("만료된 토큰입니다."); + return false; + } + return true; + } + + // RefreshToken에서 id 추출 + public Long extractIdFromRefreshToken(String token) throws Exception { + DecodedJWT jwt = JWT.require(algorithm) + .build() + .verify(token); + + String idString = jwt.getSubject(); + return Long.parseLong(idString); + } + + // RefreshToken에서 randomId 추출 + public String extractRandomIdFromRefreshToken(String token) throws Exception { + DecodedJWT jwt = JWT.require(algorithm) + .build() + .verify(token); + + return jwt.getClaim("RandomId").asString(); + } + + // AccessToken에서 id 추출 + public Long extractIdFromAccessToken(String token) throws Exception { + DecodedJWT jwt = JWT.require(algorithm) + .build() + .verify(token); + + String idString = jwt.getSubject(); + return Long.parseLong(idString); + } +} \ No newline at end of file diff --git a/docker-test-server/src/main/java/com/example/server/model/Token.java b/docker-test-server/src/main/java/com/example/server/model/Token.java new file mode 100644 index 0000000..b5c25f9 --- /dev/null +++ b/docker-test-server/src/main/java/com/example/server/model/Token.java @@ -0,0 +1,13 @@ +package com.example.server.model; + +import lombok.AllArgsConstructor; +import lombok.Data; +import lombok.NoArgsConstructor; + +@Data +@NoArgsConstructor +@AllArgsConstructor +public class Token { + private String AccessToken; + private String RefreshToken; +} diff --git a/docker-test-server/src/main/java/com/example/server/model/User.java b/docker-test-server/src/main/java/com/example/server/model/User.java index 6deb484..8a48df2 100644 --- a/docker-test-server/src/main/java/com/example/server/model/User.java +++ b/docker-test-server/src/main/java/com/example/server/model/User.java @@ -1,7 +1,5 @@ package com.example.server.model; -import java.time.LocalDateTime; - import javax.persistence.Column; import javax.persistence.Entity; import javax.persistence.Id; @@ -27,15 +25,6 @@ public class User { @Column(name = "pet_weight") private Integer petWeight; - @Column(name = "access_token") - private String accessToken; - - @Column(name = "expires_in") - private LocalDateTime expiresIn; - - @Column(name = "refresh_token") - private String refreshToken; - - @Column(name = "refresh_token_expires_in") - private LocalDateTime refreshTokenExpiresIn; + @Column(name = "random_id") + private String randomId; } \ No newline at end of file diff --git a/docker-test-server/src/main/java/com/example/server/model/UserPet.java b/docker-test-server/src/main/java/com/example/server/model/UserPet.java index 219b5a1..72b27cb 100644 --- a/docker-test-server/src/main/java/com/example/server/model/UserPet.java +++ b/docker-test-server/src/main/java/com/example/server/model/UserPet.java @@ -1,13 +1,17 @@ package com.example.server.model; +import javax.validation.constraints.NotNull; + import lombok.AllArgsConstructor; -import lombok.Data; +import lombok.Getter; import lombok.NoArgsConstructor; -@Data +@Getter @NoArgsConstructor @AllArgsConstructor public class UserPet { + @NotNull(message = "펫 이름은 필수입니다") private String petName; + @NotNull(message = "펫 무게는 필수입니다") private Integer petWeight; } diff --git a/docker-test-server/src/main/java/com/example/server/repository/UserRepository.java b/docker-test-server/src/main/java/com/example/server/repository/UserRepository.java index a68fe02..0387cf9 100644 --- a/docker-test-server/src/main/java/com/example/server/repository/UserRepository.java +++ b/docker-test-server/src/main/java/com/example/server/repository/UserRepository.java @@ -14,41 +14,27 @@ @Repository public interface UserRepository extends JpaRepository { - @Query("SELECT CASE WHEN COUNT(u) > 0 THEN true ELSE false END FROM User u WHERE u.accessToken = :accessToken") - boolean existsByAccessToken(@Param("accessToken") String accessToken); - - @Query("SELECT u.refreshToken FROM User u WHERE u.accessToken = :accessToken") - String getRefreshTokenByAccessToken(@Param("accessToken") String accessToken); - - @Query("SELECT CASE WHEN COUNT(u) > 0 THEN true ELSE false END FROM User u WHERE u.accessToken = :accessToken AND u.expiresIn < CURRENT_TIMESTAMP") - boolean isAccessTokenInvalid(@Param("accessToken") String accessToken); - - @Query("SELECT CASE WHEN COUNT(u) > 0 THEN true ELSE false END FROM User u WHERE u.refreshToken = :refreshToken AND u.refreshTokenExpiresIn < CURRENT_TIMESTAMP") - boolean isRefreshTokenInvalid(@Param("refreshToken") String refreshToken); - @Query("SELECT CASE WHEN COUNT(u) > 0 THEN true ELSE false END FROM User u WHERE u.id = :id") boolean existsById(@Param("id") Long id); + @Query("SELECT CASE WHEN COUNT(u) > 0 THEN true ELSE false END FROM User u WHERE u.id = :id AND u.randomId = :randomId") + boolean existsByIdAndRandomId(@Param("id") Long id, @Param("randomId") String randomId); + @Modifying @Transactional - @Query(value = "INSERT INTO user_tb (id, pet_name, pet_weight, access_token, expires_in, refresh_token, refresh_token_expires_in) VALUES (:#{#user.id}, :#{#user.petName}, :#{#user.petWeight}, :#{#user.accessToken}, :#{#user.expiresIn}, :#{#user.refreshToken}, :#{#user.refreshTokenExpiresIn})", nativeQuery = true) + @Query(value = "INSERT INTO user_tb (id, pet_name, pet_weight, random_id) VALUES (:#{#user.id}, :#{#user.petName}, :#{#user.petWeight}, :#{#user.randomId})", nativeQuery = true) void insertUserInformation(@Param("user") User user); - @Modifying - @Transactional - @Query(value = "UPDATE user_tb u SET u.access_token=:accessToken, u.expires_in=:expiresIn, u.refresh_token=:refreshToken, u.refresh_token_expires_in=:refreshTokenExpiresIn WHERE u.id = :id", nativeQuery = true) - void updateUserTokenInformationById(@Param("id") Long id, @Param("accessToken") String accessToken, @Param("expiresIn") LocalDateTime expiresIn, @Param("refreshToken") String refreshToken, @Param("refreshTokenExpiresIn") LocalDateTime refreshTokenExpiresIn); - - @Query("SELECT u FROM User u WHERE u.accessToken = :accessToken") - User getUserInformationByAccessToken(@Param("accessToken") String accessToken); + @Query("SELECT u FROM User u WHERE u.id = :id") + User getUserInformationByAccessToken(@Param("id") Long id); @Modifying @Transactional - @Query(value = "UPDATE user_tb u SET u.pet_name=:petName, u.pet_weight=:petWeight WHERE u.access_token=:accessToken", nativeQuery = true) - void setUserPetInformationByAccessToken(@Param("accessToken") String accessToken, @Param("petName") String petName, @Param("petWeight") Integer petWeight); + @Query(value = "UPDATE user_tb u SET u.pet_name=:petName, u.pet_weight=:petWeight WHERE u.id=:id", nativeQuery = true) + void setUserPetInformationByAccessToken(@Param("id") Long id, @Param("petName") String petName, @Param("petWeight") Integer petWeight); @Modifying @Transactional - @Query(value = "UPDATE user_tb u SET u.access_token=:accessToken, u.expires_in=:expiresIn WHERE u.id = :id", nativeQuery = true) - void updateAccessTokenById(@Param("id") Long id, @Param("accessToken") String accessToken, @Param("expiresIn") LocalDateTime expiresIn); + @Query(value = "UPDATE user_tb u SET u.random_id=:randomId, u.random_id=:randomId WHERE u.id = :id", nativeQuery = true) + void updateRandomIdByUserId(@Param("id") Long id, @Param("randomId") String randomId); } \ No newline at end of file diff --git a/docker-test-server/src/main/java/com/example/server/service/HomeService.java b/docker-test-server/src/main/java/com/example/server/service/HomeService.java index cf9eb60..e365432 100644 --- a/docker-test-server/src/main/java/com/example/server/service/HomeService.java +++ b/docker-test-server/src/main/java/com/example/server/service/HomeService.java @@ -12,7 +12,7 @@ public class HomeService { private final UserRepository userRepository; - public User getPetInformation(String AccessToken) throws Exception{ - return userRepository.getUserInformationByAccessToken(AccessToken); + public User getPetInformation(Long userId) throws Exception{ + return userRepository.getUserInformationByAccessToken(userId); } } \ No newline at end of file diff --git a/docker-test-server/src/main/java/com/example/server/service/InvalidTokenService.java b/docker-test-server/src/main/java/com/example/server/service/InvalidTokenService.java index ca2b9af..0ec9ae7 100644 --- a/docker-test-server/src/main/java/com/example/server/service/InvalidTokenService.java +++ b/docker-test-server/src/main/java/com/example/server/service/InvalidTokenService.java @@ -2,8 +2,6 @@ import org.springframework.stereotype.Service; -import com.example.server.error.CException; -import com.example.server.error.ErrorCode; import com.example.server.repository.UserRepository; import lombok.RequiredArgsConstructor; @@ -13,40 +11,7 @@ public class InvalidTokenService { private final UserRepository userRepository; - /* Input : Token, Output : Boolean - * 1. AccessToken 유(2)/무(401) - * 2. AccessToken Expire Yes(2-1)/No(3) - * 2-1. RefreshToken 유(2-2)/무(401) - * 2-2. RefreshToken Expire Yes(401)/No(2-3) - * 2-3. AccessToken 재발급(402) - * 3. return - * Tip. Token 유/무는 데이터베이스로 Check한다. - */ - public void isTokenInvalid(String AccessToken) throws Exception { - // 1. AccessToken 유(2)/무(401) - boolean flagAccessToken = userRepository.existsByAccessToken(AccessToken); - if (flagAccessToken == false) - throw new CException(ErrorCode.INVALID_TOKEN); - - // 2. AccessToken Expire Yes(2-1)/No(3) - boolean flagAccessTokenExpire = userRepository.isAccessTokenInvalid(AccessToken); - if (flagAccessTokenExpire == false) { - return; - } - - // 2-1. RefreshToken 유(2-2)/무(401) - String RefreshToken = userRepository.getRefreshTokenByAccessToken(AccessToken); - if(RefreshToken == null) { - throw new CException(ErrorCode.INVALID_TOKEN); - } - - // 2-2. RefreshToken Expire Yes(401)/No(2-3) - boolean flagRefreshTokenExpire = userRepository.isRefreshTokenInvalid(RefreshToken); - if(flagRefreshTokenExpire == true) { - throw new CException(ErrorCode.INVALID_TOKEN); - } - - // 2-3. AccessToken 재발급(402) - throw new CException(ErrorCode.REESSUIE_TOKEN); + public boolean existsById(Long userId) throws Exception{ + return userRepository.existsById(userId); } } diff --git a/docker-test-server/src/main/java/com/example/server/service/LoginService.java b/docker-test-server/src/main/java/com/example/server/service/LoginService.java index 3e93319..a99ebc7 100644 --- a/docker-test-server/src/main/java/com/example/server/service/LoginService.java +++ b/docker-test-server/src/main/java/com/example/server/service/LoginService.java @@ -1,7 +1,5 @@ package com.example.server.service; -import java.time.LocalDateTime; - import org.springframework.http.HttpEntity; import org.springframework.http.HttpHeaders; import org.springframework.http.MediaType; @@ -10,8 +8,6 @@ import org.springframework.util.MultiValueMap; import org.springframework.web.client.RestTemplate; -import com.example.server.error.CException; -import com.example.server.error.ErrorCode; import com.example.server.model.UserId; import com.example.server.repository.UserRepository; @@ -24,17 +20,10 @@ public class LoginService { private final RestTemplate restTemplate; private final UserRepository userRepository; - // 0. 유효하지 않은 토큰이면 (401) - // 1. AccessToken으로 UserID가져오기 - // 2. id로 데이터베이스에 id값이 있는지 확인 - // 3-1. 있으면 이미 회원가입한 사용자 (403), Token update할 것. - // 3-2. 없으면 회원가입으로 이동 (200) - - // Input : AccessToken, Output : status(200, 401, 403) - // Output(403) : 이미 재가입 Yes -> 데이터 Update -> 홈페이지 - // Output(401) : 유효하지 않은 토큰 - // Output(200) : 재가입 No -> 회원가입 페이지 - public void isUserRejoin(String AccessToken, Integer ExpiresIn, String RefreshToken, Integer RefreshTokenExpiresIn) throws Exception { + // Kakao Open Api에 AccessToken으로 UserId 가져오는 메소드 + // Input : AccessToken(KakaoAccessToken) + // Output : UserId (Type : Long) + public Long getUserIdByKakaoOpenApi(String AccessToken) throws Exception { HttpHeaders headers = new HttpHeaders(); headers.setContentType(MediaType.APPLICATION_FORM_URLENCODED); headers.add("Authorization", "Bearer " + AccessToken); @@ -43,34 +32,18 @@ public void isUserRejoin(String AccessToken, Integer ExpiresIn, String RefreshTo HttpEntity> httpEntity = new HttpEntity<>(headers); ResponseEntity responseEntity; - try { - responseEntity = restTemplate.postForEntity( - GET_USER_INFORMATION_URL, - httpEntity, - UserId.class - ); - } catch(Exception e) { - throw new CException(ErrorCode.INVALID_TOKEN); - } + responseEntity = restTemplate.postForEntity(GET_USER_INFORMATION_URL, httpEntity, UserId.class); UserId userId = responseEntity.getBody(); - if(userId == null) { - throw new CException(ErrorCode.INTERNAL_SERVER_ERROR); - } - boolean isIdFlag = userRepository.existsById(userId.getId()); + return userId.getId(); + } + + public boolean getUserIdByDatabase(Long userId) throws Exception { + return userRepository.existsById(userId); + } - // 이미 회원가입한 사용자(403오류), Token update후 홈페이지로 이동. - if(isIdFlag == true) { - LocalDateTime ExpiresInTime = LocalDateTime.now().plusSeconds(ExpiresIn); - System.out.println(ExpiresIn); - System.out.println(LocalDateTime.now()); - System.out.println(ExpiresInTime); - LocalDateTime RefreshTokenExpiresInTime = LocalDateTime.now().plusSeconds(RefreshTokenExpiresIn); - - userRepository.updateUserTokenInformationById(userId.getId(), AccessToken, ExpiresInTime, AccessToken, RefreshTokenExpiresInTime); - - throw new CException(ErrorCode.ALREADY_REGISTER_USER); - } + public void updateRandomIdByUserId(Long userId, String RandomID) { + userRepository.updateRandomIdByUserId(userId, RandomID); } } diff --git a/docker-test-server/src/main/java/com/example/server/service/RefreshTokenService.java b/docker-test-server/src/main/java/com/example/server/service/RefreshTokenService.java new file mode 100644 index 0000000..bd61c73 --- /dev/null +++ b/docker-test-server/src/main/java/com/example/server/service/RefreshTokenService.java @@ -0,0 +1,21 @@ +package com.example.server.service; + +import org.springframework.stereotype.Service; + +import com.example.server.repository.UserRepository; + +import lombok.RequiredArgsConstructor; + +@Service +@RequiredArgsConstructor +public class RefreshTokenService { + private final UserRepository userRepository; + + public boolean checkIdAndRandomId(Long id, String RandomID) throws Exception { + return userRepository.existsByIdAndRandomId(id, RandomID); + } + + public void updateRandomIdByUserId(Long userId, String RandomID) { + userRepository.updateRandomIdByUserId(userId, RandomID); + } +} diff --git a/docker-test-server/src/main/java/com/example/server/service/RegisterService.java b/docker-test-server/src/main/java/com/example/server/service/RegisterService.java index 4770df9..aab81dc 100644 --- a/docker-test-server/src/main/java/com/example/server/service/RegisterService.java +++ b/docker-test-server/src/main/java/com/example/server/service/RegisterService.java @@ -1,6 +1,5 @@ package com.example.server.service; -import java.time.LocalDateTime; import org.springframework.http.HttpEntity; import org.springframework.http.HttpHeaders; @@ -10,8 +9,6 @@ import org.springframework.util.MultiValueMap; import org.springframework.web.client.RestTemplate; -import com.example.server.error.CException; -import com.example.server.error.ErrorCode; import com.example.server.model.User; import com.example.server.model.UserId; import com.example.server.repository.UserRepository; @@ -25,16 +22,10 @@ public class RegisterService { private final RestTemplate restTemplate; private final UserRepository userRepository; - // AccessToken으로 UserID가져오기 - // Input : AccessToken, Output : status(200, 401, 500) - public void isUserRejoin( - String AccessToken, - Integer ExpiresIn, - String RefreshToken, - Integer RefreshTokenExpiresIn, - String PetName, - Integer PetWeight) throws Exception { - // ID값 가져오기 + // Kakao Open Api에 AccessToken으로 UserId 가져오는 메소드 + // Input : AccessToken(KakaoAccessToken) + // Output : UserId (Type : Long) + public Long getUserIdByKakaoOpenApi(String AccessToken) throws Exception { HttpHeaders headers = new HttpHeaders(); headers.setContentType(MediaType.APPLICATION_FORM_URLENCODED); headers.add("Authorization", "Bearer " + AccessToken); @@ -43,32 +34,32 @@ public void isUserRejoin( HttpEntity> httpEntity = new HttpEntity<>(headers); ResponseEntity responseEntity; - try { - responseEntity = restTemplate.postForEntity( - GET_USER_INFORMATION_URL, - httpEntity, - UserId.class - ); - } catch(Exception e) { - throw new CException(ErrorCode.INVALID_TOKEN); - } + responseEntity = restTemplate.postForEntity(GET_USER_INFORMATION_URL, httpEntity, UserId.class); UserId userId = responseEntity.getBody(); - if(userId == null) { - throw new CException(ErrorCode.INTERNAL_SERVER_ERROR); - } - - // 시간 변형 - LocalDateTime ExpiresInTime = LocalDateTime.now().plusSeconds(ExpiresIn); - LocalDateTime RefreshTokenExpiresInTime = LocalDateTime.now().plusSeconds(RefreshTokenExpiresIn); - User user = new User(userId.getId(), - PetName, - PetWeight, - AccessToken, - ExpiresInTime, - RefreshToken, - RefreshTokenExpiresInTime); + return userId.getId(); + } + + public boolean getUserIdByDatabase(Long userId) throws Exception { + return userRepository.existsById(userId); + } + + // TODO : 수정 + // AccessToken으로 UserID가져오기 + // Input : AccessToken, Output : status(200, 401, 500) + public void createUserInfo( + Long userId, + String RandomID, + String PetName, + Integer PetWeight) throws Exception { + + User user = new User( + userId, + PetName, + PetWeight, + RandomID + ); // Database에 Data 저장. userRepository.insertUserInformation(user); diff --git a/docker-test-server/src/main/java/com/example/server/service/UpdateAccessService.java b/docker-test-server/src/main/java/com/example/server/service/UpdateAccessService.java deleted file mode 100644 index df732c3..0000000 --- a/docker-test-server/src/main/java/com/example/server/service/UpdateAccessService.java +++ /dev/null @@ -1,55 +0,0 @@ -package com.example.server.service; - -import java.time.LocalDateTime; - -import org.springframework.http.HttpEntity; -import org.springframework.http.HttpHeaders; -import org.springframework.http.MediaType; -import org.springframework.http.ResponseEntity; -import org.springframework.stereotype.Service; -import org.springframework.util.MultiValueMap; -import org.springframework.web.client.RestTemplate; - -import com.example.server.error.CException; -import com.example.server.error.ErrorCode; -import com.example.server.model.UserId; -import com.example.server.repository.UserRepository; - -import lombok.RequiredArgsConstructor; - -@Service -@RequiredArgsConstructor -public class UpdateAccessService { - private String GET_USER_INFORMATION_URL="https://kapi.kakao.com/v2/user/me"; - private RestTemplate restTemplate; - private UserRepository userRepository; - - public void updateAccessTokenById(String AccessToken, Integer ExpiresIn) { - HttpHeaders headers = new HttpHeaders(); - headers.setContentType(MediaType.APPLICATION_FORM_URLENCODED); - headers.add("Authorization", "Bearer " + AccessToken); - headers.add("Content-Type", "application/x-www-form-urlencoded;charset=utf-8"); - - HttpEntity> httpEntity = new HttpEntity<>(headers); - - ResponseEntity responseEntity; - try { - responseEntity = restTemplate.postForEntity( - GET_USER_INFORMATION_URL, - httpEntity, - UserId.class - ); - } catch(Exception e) { - throw new CException(ErrorCode.INVALID_TOKEN); - } - - UserId userId = responseEntity.getBody(); - if(userId == null) { - throw new CException(ErrorCode.INTERNAL_SERVER_ERROR); - } - - LocalDateTime ExpiresInTime = LocalDateTime.now().plusSeconds(ExpiresIn); - - userRepository.updateAccessTokenById(userId.getId(), AccessToken, ExpiresInTime); - } -} diff --git a/docker-test-server/src/main/java/com/example/server/service/UserService.java b/docker-test-server/src/main/java/com/example/server/service/UserService.java index 85d8688..d02b7a2 100644 --- a/docker-test-server/src/main/java/com/example/server/service/UserService.java +++ b/docker-test-server/src/main/java/com/example/server/service/UserService.java @@ -12,11 +12,11 @@ public class UserService { private UserRepository userRepository; - public User getPetInformation(String AccessToken) throws Exception{ - return userRepository.getUserInformationByAccessToken(AccessToken); + public User getPetInformation(Long id) throws Exception{ + return userRepository.getUserInformationByAccessToken(id); } - public void setPetInformation(String AccessToken, String PetName, Integer PetWeight) throws Exception { - userRepository.setUserPetInformationByAccessToken(AccessToken, PetName, PetWeight); + public void setPetInformation(Long id, String PetName, Integer PetWeight) throws Exception { + userRepository.setUserPetInformationByAccessToken(id, PetName, PetWeight); } }