Today I Learned
(24.05.30)[7주차] Access Token과 Refresh Token 구현
JWT Access Token과 Refresh Token
- 어제 정리한 내용을 기반으로 내 자신 나름대로 Spring Security를 사용하지 않고, 코드를 짜려고 했고 스스로 코드를 분석하고자 한다.
- 작동하는데는 이상이 없고, 후에 반드시 변경점을 재포스트 할 수 있도록!
기존 JWT 활용 로그인 환경에서 Access Token / Refresh Token 구현 해보기
- Spring Security (Authentication Filter, Authorization Filter 등)을 사용하지 않고 Controller - Service - Repository 구조에서 실행될 수 있도록 구현
- 로그인 진행할 때만 Filter를 사용할 수 있도록 세팅
public JwtAuthenticationFilter(JwtUtil jwtUtil, UserRepository userRepository, RefreshTokenRepository refreshTokenRepository) {
this.jwtUtil = jwtUtil;
this.userRepository = userRepository;
this.refreshTokenRepository = refreshTokenRepository;
setFilterProcessesUrl("/api/user/login");
}
1. JWT 하나만 쓴 부분을 단순히 Access Token으로 대체 (추가 코드 X)
2. (Access 토큰이 만료가 되어 Server로 부터 재발급 받으라는 메시지를 받은 후) Access Token 재발급 요청
/*Access Token 발급*/
@PostMapping("/token")
public String createToken(HttpServletRequest request, HttpServletResponse response) {
return refreshTokenService.createToken(request, response);
}
- 원래는 필터를 거쳐서 UserDetails를 매개변수로 받거나, Authentication을 받아야하나 Controller단에서 POST 메서드를 통해서 바로 서블릿 Request를 받아오는 걸로 변경
3. Server는 DB에 저장되어있는 Refresh Token과 비교 후, 일치할 경우 Access Token 발급 후, 두 Token을 Client에 응답
- Refresh Token DB확인
- Refresh Token만 저장하는 DB와 연결되어있는 RefreshTokenRepository를 주입받아서 사용
// Refresh Token DB확인
String token = jwtUtil.getRefreshTokenFromHeader(request); // Refresh Token 찾기
RefreshToken refreshToken = refreshTokenRepository.findByToken(token).orElseThrow(
()-> new TokenException("토큰이 유효하지 않습니다.")
- Refresh Token 검증
- 만료가 되었기 때문에, DB에서 삭제
// Refresh Token 검증
if (!jwtUtil.validateToken(token)) {
refreshTokenRepository.delete(refreshToken);
throw new TokenException("로그인을 다시 해주세요.");
}
- 사용자 - Refresh Token 확인
// 사용자 - Refresh Token 확인
User user = jwtUtil.getUserFromHeader(request); // 해당 토큰에 맞는 사용자 정보 찾기
String usernameOfToken = jwtUtil.getUserInfoFromToken(refreshToken.getToken()).getSubject();
if (!usernameOfToken.equals(user.getUsername())) {
throw new TokenException("토큰이 유효하지 않습니다.");
}
- Access Token 발급 순
- addPrefix는 Header에 넣기 위해 "Bearer "를 붙여서
// Access Token 발급
String accessToken = jwtUtil.createAccessToken(user.getUsername(), user.getRole());
response.addHeader(JwtUtil.ACCESS_TOKEN_HEADER, jwtUtil.addPrefix(accessToken));
return "토큰 발급 완료";
단계별로 코드를 짠 다음에 Service 단에서 합쳐서 실행
코드가 중간에 바뀐 부분이 있었기 때문에 적은 양이라도 맞는지 아닌지 확인하고 고치고하는데 하루를 전부 사용해서
아쉬운 부분이다.
추후에 바꿀일 있으면 다시 피드백과 함께 포스팅
'Today I Learned' 카테고리의 다른 글
(24.06.03)[8주차] PriorityQueue (1) | 2024.06.03 |
---|---|
(24.05.31)[7주차] Spring Security Filter에서의 Password Encoder (1) | 2024.05.31 |
(24.05.29)[7주차] JWT Access Token과 Refresh Token 정리 (0) | 2024.05.29 |
(24.05.28)[7주차] void 반환 타입일 때의 response 사용 (0) | 2024.05.28 |
(24.05.27)[7주차] Validation 의 @Pattern (0) | 2024.05.27 |