Refresh Token(with mySQL)

이민호·2024년 6월 7일
0

요 며칠간 refresh token을 어떻게 프로젝트에 적용 시킬까 고민을 열심히 하고 수많은 포스팅을 들락 거렸다.
머리를 싸매고, 약간 뒹굴거리며 생각해낸 방법

  • 인증 성공 시 2가지 token을 생성
  • HttpResponse의 header 부분에 access token 과 refresh token을 추가
protected void successfulAuthentication(HttpServletRequest request, HttpServletResponse response, FilterChain chain, Authentication authResult) {
        User user = ((UserDetailsImpl) authResult.getPrincipal()).getUser();
        String userId = user.getUserId();
		
        // 토큰 생성시 유효기간 차이를 두고 생성
        String token = jwtService.createToken(userId);
        String refreshToken = jwtService.createRefreshToken(userId);
		
        // 헤더의 이름을 변경해서 2가지 토큰을 response header에 추가
        response.addHeader(JwtService.AUTHORIZATION_HEADER, token);
        response.addHeader(JwtService.REFRESH_TOKEN_HEADER, refreshToken);

        user.setRefreshToken(refreshToken);
        userRepository.save(user);
    }
  • 동시에 생성된 refresh token을 사용자 엔티티에 추가
    -> 데이터 베이스에 refresh token이 저장됨
  • 이후 인가 단계에서 access token 만료시, refresh token에 대한 검증 단계를 추가
    -> refresh token의 존재여부 (isNull)
    -> 사용자의 토큰 (DB) HttpResponse에 담겼던 토큰이 같은지
//JwtAuthorizationFilter.java
	protected void doFilterInternal(HttpServletRequest req, HttpServletResponse res, FilterChain filterChain) throws ServletException, IOException {
		...
			String userRefreshToken = jwtService.substringToken(user.getRefreshToken());
            String refreshToken = jwtService.getRefreshJwtFromHeader(req);

            log.info("User's Refresh Token: " + userRefreshToken);
            log.info("response's Refresh Token: " + refreshToken);

            // 유저가 보유한 토큰과 httpservlet의 토큰이 같은지 비교
            if (userRefreshToken.equals(refreshToken)) {
                // 토큰이 만료된 경우
                if (jwtService.isTokenExpired(tokenValue)) {
                    // 리프레시 토큰이 유효한 경우, 새로운 토큰 생성
                    if (!jwtService.isRefreshTokenExpired(userRefreshToken)) {
                        jwtService.createToken(user.getUserId());
                        System.out.println("jwtService.createToken(user.getUserId()) = " + jwtService.createToken(user.getUserId()));
                        jwtService.createRefreshToken(user.getUserId());
                        log.info("새로운 토큰이 생성되었습니다.");
                        setAuthentication(claims.getSubject());
                        filterChain.doFilter(req, res);
                    } else {
                        // 리프레시 토큰도 만료된 경우
                        throw new IllegalArgumentException("다시 재로그인해주세요");
                    }
                } else {
                    // 토큰이 유효한 경우
                    setAuthentication(claims.getSubject());
                }
            } else {
                throw new IllegalArgumentException("토큰의 정보가 일치하지 않습니다.");
            }
        }
        ...
profile
둘뺌

0개의 댓글