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

[HW/#15] 6차 세미나 실습 과제 #16

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

[HW/#15] 6차 세미나 실습 과제 #16

wants to merge 10 commits into from

Conversation

PicturePark1101
Copy link
Contributor

@PicturePark1101 PicturePark1101 commented May 30, 2024

API 명세서

API 명세서

기능

1. 회원가입시 리프레시 토큰도 함께 반환

  • 액세스 토큰 만료는 1시간, 리프레시는 2주로 설정했습니다.
  • 발급 로직은 두 토큰이 동일
  private static final Long ACCESS_TOKEN_EXPIRATION_TIME = 60 * 60 * 1000L;
  private static final Long REFRESH_TOKEN_EXPIRATION_TIME = 60 * 60 * 24 * 1000L * 14;

Service #createMember()

  • 해당 함수에 리프레시 토큰 발급하는 로직, 발급받은 리프레시 토큰을 레디스에 저장하는 로직을 추가했습니다.
  • Token의 id는 memberId로 설정했습니다.(member당 토큰 1개이므로)
...
private final RedisTokenRepository redisTokenRepository;
....생략
  
  @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 refreshToekn = jwtTokenProvider.issueRefreshToken(
        UserAuthentication.createUserAuthentication(memberId)
    );

    //리프레시 토큰 레디스에 저장(id는 memberId로..)
    redisTokenRepository.save(Token.of(memberId, refreshToekn));

    return UserJoinResponse.of(memberId.toString(), accessToken, refreshToekn);

PostMan 테스트

스크린샷 2024-05-30 오후 6 57 47

Redis에 리프레시 토큰 저장

스크린샷 2024-05-30 오후 6 57 27

2. 리프레시 토큰을 통한 액세스 토큰 재발급

Controller #regenerateToken()

  • header보단 body로 받는게 보안상 좋다고 들어서 @ RequestBody를 통해 토큰을 받도록 하였습니다.
  @PostMapping("/regenerate-token")
  public ResponseEntity<SuccessStatusResponse> regenerateToken(
      @RequestBody RegenerateAccessTokenRequestDto regenerateAccessTokenRequestDto
  ) {
    return ResponseEntity.ok()
        .body(SuccessStatusResponse.of(
            SuccessMessage.ACCESS_TOKEN_REGENERATE_SUCCESS,
            memberService.getNewAccessToken(regenerateAccessTokenRequestDto)));
  }

Service #getNewAccessToken()

  • 요청으로 받은 리프레시 토큰이 레디스에 있는지 찾아봅니다. 없으면 만료가 된 것이므로 에러메시지를 반환하도록 했습니다.
  • 존재하는 토큰이 유효한 토큰인지 한번 더 체크합니다.validateToken()
  • 유효하다면 새 엑세스 토큰을 생성해서 리턴합니다.
...
   private final RedisTokenRepository redisTokenRepository;
...생략
  
  @Transactional
  public RegenerateAccessTokenResponseDto getNewAccessToken(
      RegenerateAccessTokenRequestDto regenerateAccessTokenRequestDto) {

    String refreshToken = regenerateAccessTokenRequestDto.refreshToken();

    // 리프레시 토큰이 redis에 존재하는지 확인하기. 존재하면 만료되지 않은 것임.(일정 시간 후 사라지므로)
    // 없으면 다시 로그인하라는 에러메시지 보내기
    Token token = getRefreshToken(refreshToken);

    // 존재하는 토큰이 유효한 토큰인지(제대로 된 토큰인지) 다시 검증
    jwtTokenProvider.validateToken(token.getRefreshToken());

    // 유효하다면 액세스 토큰 재발급
    String accessToken = jwtTokenProvider.issueAccessToken(
        UserAuthentication.createUserAuthentication(token.getId())
    );

    return RegenerateAccessTokenResponseDto.of(accessToken);
  }
  
  ...생략
//redis에 refreshToken 존재하는지. 존재하면 리턴
   public Token getRefreshToken(String refreshToken) {
    return redisTokenRepository.findByRefreshToken(refreshToken).orElseThrow(
        () -> new UnauthorizedException(ErrorMessage.JWT_UNAUTHORIZED_REFRESH_EXPIRED_EXCEPTION));
  }

PostMan 테스트

스크린샷 2024-05-30 오후 6 54 50

질문

  • RedisTokenService를 따로 분리할까 했는데, 리프레시 토큰에 관한 로직은 MemberService에만 존재하고, 앞으로도 그럴 것 같아서 분리하지 않았습니다. 분리하는게 좋을까요…?
  • 주워듣기론 header보단 body가 보안상 좋다고 들어서 만료 기간이 긴 리프레시 토큰은 body로 보냈는데 보통 어떻게 하는지 궁금합니다.
  • 토큰의 경우 유실되어도 그렇게 치명적인 데이터는 아니니(다시 발급받으면 되니까) 메인 DB와 Redis 2곳 모두에 저장할 필요는 없겠죠..?

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
✨ feature 기능 추가 📚 homework 과제 👊🏻 pull request PR 날림 ♻️ refactor 코드 리팩토링
Projects
None yet
Development

Successfully merging this pull request may close these issues.

[HW] 6차 세미나 실습 과제
1 participant