코드 그라데이션
토큰 API 구현하기 본문
토큰 API 구현하기
- 여기서는 리프레시 토큰을 전달방ㄷ아 검증하고,
유효한 리프레시 토큰이라면 새로운 액세스 토큰을 생성하는 토큰 API를 구현한다.
- 토큰 서비스, 컨트롤러를 차례대로 구현한다.
1. 토큰 서비스 추가하기
- 리프레시 토큰을 전달받아 토큰 제공자를 사용해 새로운 액세스 토큰을 만드는 클래스
1-1. UserService 에 findById() 추가하기
@RequiredArgsConstructor
@Service
public class UserService {
private final UserRepository userRepository;
public Long save(AddUserRequest dto) {
BCryptPasswordEncoder encoder = new BCryptPasswordEncoder();
// UserRepository를 통해 새 사용자를 저장.
// - AddUserRequest에서 전달된 이메일과 비밀번호를 사용하여 새 사용자를 생성.
// - 비밀번호는 BCryptPasswordEncoder를 사용하여 안전하게 해싱됨
return userRepository.save(User.builder()
.email(dto.getEmail())
.password(encoder.encode(dto.getPassword()))
.build()).getId(); // 저장된 사용자의 ID를 반환
}
//추가
public User findById(Long userId) {
return userRepository.findById(userId)
.orElseThrow(() -> new IllegalArgumentException("Unexpected user"));
}
}
1-2. RefreshTokenService에 findByRefreshToken() 메서드 구현
@RequiredArgsConstructor
@Service
public class RefreshTokenService {
private final RefreshTokenRepository refreshTokenRepository;
// 리프레시 토큰 조회 메서드
public RefreshToken findByRefreshToken(String refreshToken) {
return refreshTokenRepository.findByRefreshToken(refreshToken)
.orElseThrow(() -> new IllegalArgumentException("Unexpected token"));
}
}
2. 컨트롤러 추가하기
2-1. DTO 추가하기
1) CreateAccessTokenRequest
@Getter
@Setter
public class CreateAccessTokenRequest {
private String refreshToken;
}
2) CreateAccessTokenResponse
@Getter
@AllArgsConstructor
public class CreateAccessTokenResponse {
private String accessToken;
}
2-2. 컨트롤러 추가 - TokenApiController
@RestController
@RequiredArgsConstructor
public class TokenApiController {
private final TokenService tokenService;
@PostMapping("/api/token")
public ResponseEntity<CreateAccessTokenResponse> createNewAccessToken
(@RequestBody CreateAccessTokenRequest request) {
// TokenService를 사용하여 새로운 액세스 토큰 생성을 요청
String newAccessToken
= tokenService.createNewAccessToken(request.getRefreshToken());
// 생성된 액세스 토큰을 ResponseEntity로 래핑하여 반환
// CreateAccessTokenResponse 객체는 생성된 액세스 토큰을 포함하는 응답 데이터이다.
return ResponseEntity.status(HttpStatus.CREATED)
.body(new CreateAccessTokenResponse(newAccessToken));
}
}
2-3. 테스트 추가
개요
@SpringBootTest
@AutoConfigureMockMvc
class TokenApiControllerTest {
@Autowired
protected MockMvc mockMvc;
@Autowired
protected ObjectMapper objectMapper;
@Autowired
JwtProperties jwtProperties;
@Autowired
UserRepository userRepository;
@Autowired
RefreshTokenRepository refreshTokenRepository;
@Autowired
private WebApplicationContext context;
@BeforeEach
public void mockMvcSetUp() {
this.mockMvc = MockMvcBuilders.webAppContextSetup(context)
.build();
userRepository.deleteAll();
}
@DisplayName("createNewAccessToken: 새로운 액세스 토큰을 발급한다.")
@Test
public void createNewAccessToken() throws Exception {
// given
final String url = "/api/token";
User testUser = userRepository.save(User.builder()
.email("user@gmail.com")
.password("test")
.build());
String refreshToekn = JwtFactory.builder()
.claims(Map.of("id", testUser.getId()))
.build()
.createToken(jwtProperties);
refreshTokenRepository.save(new RefreshToken(testUser.getId(), refreshToekn));
CreateAccessTokenRequest request = new CreateAccessTokenRequest();
request.setRefreshToken(refreshToekn);
final String requestBody = objectMapper.writeValueAsString(request);
// when
ResultActions resultActions = mockMvc.perform(post(url)
.contentType(MediaType.APPLICATION_JSON_VALUE)
.content(requestBody));
// then
resultActions
.andExpect(status().isCreated())
.andExpect(jsonPath("$.accessToken").isNotEmpty());
}
}
728x90
'SpringBoot [예제] 블로그 만들기 > 시큐리티, JWT 입히기' 카테고리의 다른 글
스프링 시큐리티로 OAuth2 구현하고 적용하기 (0) | 2023.10.21 |
---|---|
JWT 서비스 구현하기 (1) | 2023.10.19 |
JWT 소개 (0) | 2023.10.18 |
[사전 지식] 토큰 기반 인증 (0) | 2023.10.18 |
시큐리티 설정, 로그인/로그아웃, 회원가입 구현 (0) | 2023.10.17 |
Comments