Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

[feat] 6차 세미나 과제 코드입니다. #8

Open
wants to merge 2 commits into
base: main
Choose a base branch
from

Conversation

choyeongju
Copy link
Member

@choyeongju choyeongju commented Jun 2, 2024

Related Issue 📌

Description ✔️

🍀 로그인 진행 시 AccessToken과 RefreshToken 함께 반환하는 로직
  • Access Token은 만료시간이 짧은 토큰이기 때문에, 만료 시간을 짧게 수정해주고, 만료 시간이 긴 Refresh Token 필드를 생성해 준다.

    private static final Long ACCESS_TOKEN_EXPIRATION_TIME = 24 * 60 * 60 * 1000L * 2;
    private static final Long REFRESH_TOKEN_EXPIRATION_TIME = 60 *  60 * 24 * 1000L * 14;
  • Access Token 생성 로직이랑 동일하게 RefreshToken을 생성해준다.

        // Refresh Token 관련 로직
        private static final Long REFRESH_TOKEN_EXPIRATION_TIME = 60 *  60 * 24 * 1000L * 14;
    
        public String issueRefreshToken(final Authentication authentication) {
            return generateToken(authentication, REFRESH_TOKEN_EXPIRATION_TIME);
        }
  • 멤버 생성 시 생성한 accessToken, refreshToken을 반환해준다. 또한, 해당 멤버에 해당하는 refreshToken을 Redis에 저장해준다.

        @Transactional
        public UserJoinResponse createMember(
                MemberCreateDto memberCreate
        ) {
            Member member = memberRepository.save(
                    Member.create(memberCreate.name(), memberCreate.part(), memberCreate.age())
            );
            Long memberId = member.getId();
            String accessToken = jwtTokenProvider.issueAccessToken( //사용자의 인증 정보를 이용하여 토큰을 발급
                    UserAuthentication.createUserAuthentication(memberId)
            );
            String refreshToken = jwtTokenProvider.issueRefreshToken(
                    UserAuthentication.createUserAuthentication(memberId)
            );
            redisTokenRepository.save(Token.of(memberId,refreshToken));
            return UserJoinResponse.of(accessToken, refreshToken, memberId.toString());
        }
  • (기타) Redis 설정 파일 구성해줘야 한다.

    @Configuration
    @RequiredArgsConstructor
    @EnableRedisRepositories
    public class RedisRepositoryConfig {
        private final RedisProperties redisProperties;
    
        @Bean
        public RedisConnectionFactory redisConnectionFactory(){
            return new LettuceConnectionFactory(redisProperties.getHost(), redisProperties.getPort());
        }
    
        @Bean
        public RedisTemplate<String, Object> redisTemplate(){
            RedisTemplate<String, Object> redisTemplate = new RedisTemplate<>();
            redisTemplate.setConnectionFactory(redisConnectionFactory());
            redisTemplate.setKeySerializer(new StringRedisSerializer());
            redisTemplate.setValueSerializer(new StringRedisSerializer());
            return redisTemplate;
        }
  • 실행결과

image

  • Redis 서버가 실행중인지 확인하는 방법!

image


🍀 Redis 활용해 Refresh Token으로 Access Token 재발급 받는 로직
  • Refresh Token 검증: 클라이언트가 제공한 Refresh Token을 검증합니다.
  • Refresh Token의 유효성 확인: Refresh Token이 유효한지 확인합니다.
  • 새로운 Access Token 발급: Refresh Token이 유효하다면 새로운 Access Token을 발급합니다.
  1. TokenController 구현

        private final RedisTokenService redisTokenService;
        private final PrincipalHandler principalHandler;
        
        @PostMapping("/refresh-token")
        public ResponseEntity<AccessTokenDto> refreshToken(){
            Long userId = principalHandler.getUserIdFromPrincipal();
            AccessTokenDto newAccessTokenResponse = redisTokenService.refreshToken(userId);
            return ResponseEntity.status(HttpStatus.CREATED)
                    .body(newAccessTokenResponse);
        }
  2. RedisTokenService 구현

  3. 실행결과

image


🍀 Redis에 저장되어 있는 RefreshToken 확인해보기
  1. redis 접속

    redis-cli
  2. KEY값(refreshToken) 으로 되어 있는 아이들 모두 확인

    KEYS *refreshToken*
  3. 결과

image

To Reviewers

@choyeongju choyeongju changed the title #seminar/6 [feat] 6차 세미나 과제 코드입니다. Jun 2, 2024
Copy link

@junggyo1020 junggyo1020 left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

PR 잘 읽어보았습니다..! 중간 중간 주석처리가 잘 되어 있어서 코드를 읽고 이해하기 쉬웠던 것 같아요:) 에러 처리 관련한 부분에서 어떤 상황에서 예외가 발생하는지에 대한 주석처리가 있으면 훨씬 좋을 것 같다는 생각이 들었습니다!! ㅎㅎ

  • 멤버 생성 API -> 이 부분은 회원가입에 대한 부분이라 로그인 시 아이디와 비밀번호가 일치하는지 확인하는 검증과정이 추가로 필요하기 떄문에 로그인 관련 API를 따로 구현을 해야한다는 생각을 하게 되었는데 구현하실 때 이부분에 대해 다른 생각이 있으셨는지가 궁금합니다!

과제하시느라 정말 고생 많으셨습니다!

Comment on lines +21 to +28
@PostMapping("/refresh-token")
public ResponseEntity<AccessTokenDto> refreshToken(){
Long userId = principalHandler.getUserIdFromPrincipal();
AccessTokenDto newAccessTokenResponse = redisTokenService.refreshToken(userId);
return ResponseEntity.status(HttpStatus.CREATED)
.body(newAccessTokenResponse);
}
}

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

위의 메서드에서 @RequestBody로 RefreshToken을 받도록 수정하면 좀 더 안전하게 토큰을 갱신할 수 있을 것 같다는 생각이 드네요..!!

@PostMapping("/refresh-token")
public ResponseEntity<AccessTokenDto> refreshToken(@RequestBody String refreshToken){
    Long userId = principalHandler.getUserIdFromPrincipal();
    AccessTokenDto newAccessTokenResponse = redisTokenService.refreshToken(userId, refreshToken);
    return ResponseEntity.status(HttpStatus.CREATED).body(newAccessTokenResponse);
}

@hyerinhwang-sailin
Copy link

과제하느라 고생많으셨습니다! redis 서버 실행 여부 확인 방법 등도 pr에 같이 명시해주셔서 좋네용! 주석도 잘 이해돼서 좋았습니다~

@jun3327
Copy link

jun3327 commented Jun 5, 2024

과제하시느라 고생하셨습니다! 궁금한 점이 있는데
RedisRepositoryConfig 파일은 어떤 이유로 정의해주셨는지 궁금합니다!

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
Projects
None yet
Development

Successfully merging this pull request may close these issues.

[week6] 세미나 6차 과제_Redis
4 participants