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

Seminar/#11 #12

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

Seminar/#11 #12

wants to merge 6 commits into from

Conversation

Yangdaehan
Copy link
Contributor

@Yangdaehan Yangdaehan commented Jun 1, 2024

이 주의 과제

  • 로그인을 진행할 때 AccessToken과 Refresh Token을 함께 반환하는 로직

  • Redis를 활용해 Refresh Token으로 Access Token을 재발급 받는 로직을 구현

  • 액세스 토큰이 만료되고 리프레시 토큰을 사용하여 새로운 액세스 토큰을 발급하는 경우, 보안성을 높이기 위해 리프레스 토큰 또한 재발급 되도록 구현하였습니다. 리프레시 토큰이 주기적으로 갱신되면, 만약 리프레시 토큰이 탈취되더라도 공격자가 사용할 수 있는 시간 범위를 줄일 수 있기 때문입니다.

요구사항 분석

  • Refresh Token 발급
    : 사용자 인증 정보를 기반으로 RefreshToken을 발급합니다.
    만료 시간(14일)을 갖게 설정

    @RedisHash(value = "", timeToLive = 60 * 60 * 24 * 1000L * 14)
    @AllArgsConstructor
    @Getter
    @Builder
    public class Token {
    @Id
    private Long id;
    @Indexed
    private String refreshToken;
    private static Token of(
    final Long id,
    final String refreshToken
    ) {
    return Token.builder()
    .id(id)
    .refreshToken(refreshToken)
    .build();
    }

  • 클라이언트에 Access Token, Refresh Token 을 저장하고 반환
    : 아래 코드는 회원을 생성하고, 회원에 대한 액세스 토큰과 리프레시 토큰을 발급한 다음 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());
    }

  • 클라이언트가 API 호출 시, 유저의 refresh token을 검증하여 access 토큰 재발급(reissue)
    : 주어진 리프레시 토큰을 사용하여 검사하고 해당 userId에 새로운 액세스 토큰, 리프레시 토큰을 발급하는 작업을 수행합니다.
    (controller)

    @PostMapping("/refresh")
    public ResponseEntity<UserJoinResponse> refreshToken(){
    UserJoinResponse userJoinResponse = memberService.refreshToken(
    principalHandler.getUserIdFromPrincipal()
    );
    return ResponseEntity.status(HttpStatus.CREATED)
    .header("Location", userJoinResponse.userId())
    .body(
    userJoinResponse
    );
    }

    (service)
    @Transactional
    public UserJoinResponse refreshToken(Long memberId) {
    if(!redisTokenRepository.existsById(String.valueOf(Long.valueOf(memberId.toString())))){
    throw new UnauthorizedException(ErrorMessage.INVALID_REFRESH_TOKEN);
    }
    findById(memberId);
    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());
    }

실행 결과

  • AccessToken, RefrestToken, userId 반환
스크린샷 2024-06-02 오후 2 26 30
  • AccessToken으로 인증해서 블로그 만들기
스크린샷 2024-06-02 오후 2 27 10
  • RefreshToken으로 AccessToken 재발급 받기
스크린샷 2024-06-02 오후 2 28 43

질문있어요!

어려워요 Redis .. 여러 도움으로 구현할 수 있었습니다.

@Yangdaehan Yangdaehan requested a review from sohyundoh June 2, 2024 05:55
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

Week 06 과제
1 participant