๋ด๊ฐ ์์ ํฌ์คํ ์์ ์ป๋ ํ ํฐ ์ธ์ฆ ๊ณผ์ ์.
[๋ฆฌํ๋ ์ ํ ํฐ ๋ฐ๊ธ ๊ณผ์ ]
โ
1. ํด๋ผ์ด์ธํธ -> ์๋ฒ : ์ธ์ฆ ์์ฒญ
2. ์๋ฒ -> ํด๋ผ์ด์ธํธ : ์ก์ธ์ค ํ ํฐ & ๋ฆฌํ๋ ์ ํ ํฐ ์๋ต
3. ์๋ฒ -> DB : ๋ฆฌํ๋ ์ ํ ํฐ์ ์ ์ฅ
4. ํด๋ผ์ด์ธํธ -> ์๋ฒ :API ์์ฒญ
5. ์๋ฒ : ํ ํฐ ์ ํจ์ฑ ๊ฒ์ฌ ํ๊ณ ์๋ต
~~ ์๊ฐ์ด ํ๋ฅด๊ณ ~~
6. ํด๋ผ์ด์ธํธ -> ์๋ฒ : (๋ง๋ฃ๋ ํ ํฐ์ผ๋ก) API ์์ฒญ
7. ์๋ฒ -> ํด๋ผ์ด์ธํธ : ํ ํฐ ๋ง๋ฃ๋๋ค๊ณ ์๋ต
8. ํด๋ผ์ด์ธํธ -> ์๋ฒ : (๋ฆฌํ๋ ์ ํ ํฐ๊ณผ ํจ๊ผ) ์ก์ธ์ค ํ ํฐ ๋ฐ๊ธ ์์ฒญ
9. ์๋ฒ -> DB : ๋ฆฌํ๋ ์ ํ ํฐ ์กฐํ & ์ ํจ์ฑ ๊ฒ์ฌ
10. ์๋ฒ -> ํด๋ผ : ๋ง์กฑํ๋ฉด, new ์ก์ธ์ค ํ ํฐ์ผ๋ก ์๋ต
11. ํด๋ผ -> ์๋ฒ : new ์ก์ธ์ค ํ ํฐ์ผ๋ก ๋ค์ ์์ฒญ...(4๋ฒ๋ถํฐ ๋ฐ๋ณต)
๐ก ์ก์ธ์ค ํ ํฐ์ด ์ ํจํ ๋
JWT ์์ฒด์ ์๋ Claim์์ userId๊ฐ์ ์ ๋ณด ๊บผ๋ด์ด
DB ์ ๊ทผ ์ํด๋ ๋จ.
๐ก ์ก์ธ์ค ํ ํฐ์ด ๋ง๋ฃ๋์ ๋
๋ฆฌํ๋ ์ ํ ํฐ ๋ฐ์์
DB์์ ๋ฆฌํ๋ ์ ํ ํฐ ์กฐํ, ํด๋น ํ ํฐ์ ๊ด๋ จ๋ userId์ป์ด์
์ ์์ธ์ค ํ ํฐ ๋ง๋ฆ
์ด๋ฒ ํฌ์คํ ์์๋,
๋ฆฌํ๋ ์ ํ ํฐ ๋ฐ์์ ์ ํจ์ฑ ๊ฒ์ฌํ๊ณ
์ ํจํ ๋ฆฌํ๋ ์ ํ ํฐ์ด๋ผ๋ฉด ์๋ก์ด accessToken๋ฐ๊ธํ๋
ํ ํฐ API๋ง๋ค๊ฑฐ์!
๋จผ์ UserService.java์ชฝ์ ๋ฉ์๋๋ฅผ ์ถ๊ฐํจ
@RequiredArgsConstructor
@Service
public class UserService {
private final UserRepository userRepository;
private final BCryptPasswordEncoder bCryptPasswordEncoder;
public Long save(AddUserRequestDto dto) {
return userRepository.save(User.builder()
.email(dto.getEmail())
.password(bCryptPasswordEncoder.encode(dto.getPassword()))
.build()).getId();
}
// ์ถ๊ฐ ๋ ๋ฉ์๋
public User findById(Long userId) {
return userRepository.findById(userId)
.orElseThrow( () -> new IllegalArgumentException("Unexpected user"));
}
}
ํ ํฐ ๊ธฐ๋ฐ ์์ฒญ์ด ๋ค์ด์จ ํ์
์ค์ ์ ์ ๋ฅผ DB์์ ํ์ธํ๊ฑฐ๋ ๊ฐ์ ธ์ฌ๋ ์ฌ์ฉ๋จ.
๋ค์์ผ๋ก service๋๋ ํ ๋ฆฌ์ RefreshTokenService.java ์ ํ์ผ ์์ฑํด์
@RequiredArgsConstructor
@Service
public class RefreshTokenService {
private final RefreshTokenRepository refreshTokenRepository;
public RefreshToken findByRefreshToken(String refreshToken) {
return refreshTokenRepository.findByRefreshToken(refreshToken)
.orElseThrow( () -> new IllegalArgumentException("Unexpected refresh token"));
}
}
์ด ๊ณผ์ ์, ์์ ๋ฆฌํ๋ ์ ํ ํฐ ๋ฐ๊ธ๊ณผ์
(๋ ธ๋์ ํ๊ดํ)
์ค 9๋ฒ์ ํด๋นํ๋ ์ฝ๋์!
service ๋๋ ํ ๋ฆฌ ๋ด์
TokenService.java ํ์ผ ์์ฑ
@RequiredArgsConstructor
@Service
public class TokenService {
private final TokenProvider tokenProvider;
private final RefreshTokenService refreshTokenService;
private final UserService userService;
public String createNewAccessToken(String refreshToken) {
// ๋ฆฌํ๋ ์ ํ ํฐ ์ ํจ์ฑ ๊ฒ์ฌ
if(!tokenProvider.validToken(refreshToken)) {
throw new IllegalArgumentException("Invalid refresh token");
}
Long userId = refreshTokenService.findByRefreshToken(refreshToken).getUserId();
User user = userService.findById(userId);
return tokenProvider.generateToken(user, Duration.ofHours(2));
}
}
์ฌ๊ธฐ์ ์์ฑํ createNewAccessToken()๋ฉ์๋๋
๋ฆฌํ๋ ์ ํ ํฐ์ ์ ๋ฌ๋ฐ๊ณ
์ ํจ์ฑ ๊ฒ์ฌํ๊ณ
์ ํจ๋ค๋ฉด ๊ทธ ๋ฆฌํ๋ ์ ํ ํฐ ๊ธฐ๋ฐ์ผ๋ก userId์ฐพ๊ณ
๊ทธ ์ ์ ํํ ์๋ก์ด accessToken์
tokenProvider.generateToken()ํด์ ๋๊ฒจ์ค.
์ปจํธ๋กค๋ฌ ์ชฝ ๋ค์ด๊ฐ๊ธฐ ์ ์ DTO๋ค๋ถํฐ ๋ง๋ค๊ฒ ์.
DTO๋๊ฐ ๋ง๋ค๊ณ ~
@Getter
@Setter
public class CreateAccessTokenRequestDto {
private String refreshToken;
}
@AllArgsConstructor
@Getter
public class CreateAccessTokenResponseDto {
private String accessToken;
}
์ปจํธ๋กค๋ฌ ์ถ๊ฐํ ์ฐจ๋ก
@RequiredArgsConstructor
@RestController
public class TokenApiController {
private final TokenService tokenService;
@PostMapping("/api/token")
public ResponseEntity<CreateAccessTokenResponseDto> createNewAccessToken(
@RequestBody CreateAccessTokenRequestDto request) {
String newAccessToken = tokenService.createNewAccessToken(request.getRefreshToken());
return ResponseEntity.status(HttpStatus.CREATED)
.body(new CreateAccessTokenResponseDto(newAccessToken));
}
}
๊ธฐ์กด ์ก์ธ์ค ํ ํฐ์ด ๋ง๋ฃ๋์ด์
๋ฆฌํ๋ ์ ํ ํฐ์ ๋ณด๋ด์ new ์์ธ์ค ํ ํฐ ์ฃผ์ธ์~
ํ ๋ ๋ณด๋ด๋ ์๋ ํฌ์ธํธ.
'Spring Security' ์นดํ ๊ณ ๋ฆฌ์ ๋ค๋ฅธ ๊ธ
| [OAuth2] ๋ด๊ฐ ๋ณด๋ ค๊ณ ๋ง๋ OAuth2 ํ๋ฆ ์ ๋ฆฌ (1) | 2025.05.16 |
|---|---|
| [Spring Security] ์ฟ ํค vs ํค๋๋ก JWT ๋ณด๋ด๊ธฐ (0) | 2025.05.15 |
| [Spring Security] Token Filter ๊ตฌํํ๊ธฐ (0) | 2025.05.05 |
| [Spring Security] SecurityContextHolder๋? (0) | 2025.05.05 |
| [Spring Boot] ํ ์คํธ์ฝ๋์์ ๋กฌ๋ณต import์๋จ (0) | 2025.05.04 |