Skip to content

Conversation

@m-a-king
Copy link
Collaborator

resolved:

📌 과제 설명

JWT 기반 인증 및 토큰 관리 기능 구현:

  • HMAC(+SHA256)기반 JWT 생성 및 검증 로직 추가
  • Redis를 활용한 RefreshToken 관리
  • AccessToken 갱신 및 통합 관리 로직 구현

👩‍💻 요구 사항과 구현 내용

  1. JWT 기본 설정

    • JWT 처리 라이브러리(JJWT) 의존성 추가, 시크릿 키 설정.
  2. 토큰 관리

    • AccessToken과 RefreshToken 검증 기간 구분을 위한 TokenType.
    • EncodedToken 레코드를 사용하여 토큰 값을 래핑하고 통합 관리.
  3. RefreshToken 관리

    • Redis를 활용한 RefreshToken 저장, 조회, 삭제 기능.
    • RefreshToken을 기반으로 AccessToken 갱신 로직.
  4. JWT 통합 서비스

    • JWT 생성, 검증, 클레임 조회, 갱신 로직을 통합 관리하는 로직.
    • 로그인 시 AccessToken 및 RefreshToken 생성 후 저장하는 로직.

✅ PR 포인트 & 궁금한 점

  • 패키지 구조와 인터페이스, 클래스(구현체)의 구조 및 네이밍이 적절한지 검토 부탁드립니다.
  • JWT 통합 관리 서비스(JwtUseCase, JwtService)가 파사드 서비스 레이어로 적합한지 검토 부탁드립니다.
  • Redis 기반 RefreshToken 관리에서 추가적인 최적화가 필요한 부분에 대한 의견을 공유 부탁드립니다.
    • 현재 Redis를 사용하여 구현했으며, Command와 Query를 구분하지 않았습니다.
  • 프론트엔드와 협의한 RefreshToken 만료 시 예외 처리 방식이 적절한지 검토 부탁드립니다.

github-actions[bot]

This comment was marked as resolved.

@github-actions github-actions bot changed the title Feature/29 JWT 기능 구현 [BUILD FAIL] Feature/29 JWT 기능 구현 Nov 23, 2024
@github-actions github-actions bot closed this Nov 23, 2024
@m-a-king m-a-king reopened this Nov 23, 2024
github-actions[bot]

This comment was marked as resolved.

@github-actions github-actions bot changed the title [BUILD FAIL] Feature/29 JWT 기능 구현 [BUILD FAIL] [BUILD FAIL] Feature/29 JWT 기능 구현 Nov 23, 2024
@github-actions github-actions bot closed this Nov 23, 2024
@m-a-king m-a-king reopened this Nov 23, 2024
github-actions[bot]

This comment was marked as resolved.

@github-actions github-actions bot changed the title [BUILD FAIL] [BUILD FAIL] Feature/29 JWT 기능 구현 [BUILD FAIL] [BUILD FAIL] [BUILD FAIL] Feature/29 JWT 기능 구현 Nov 23, 2024
@github-actions github-actions bot closed this Nov 23, 2024
@m-a-king m-a-king reopened this Nov 23, 2024
@m-a-king m-a-king closed this Nov 23, 2024
@m-a-king m-a-king reopened this Nov 23, 2024
- jjwt-api, jjwt-impl, jjwt-jackson 의존성 추가 (버전 0.12.6)
- 토큰 생성을 위한 JwtGenerator 인터페이스 추가
- 토큰 파싱을 위한 JwtParser 인터페이스 추가
- 토큰 검증을 위한 JwtValidator 인터페이스 추가
- JWT 작업 통합을 위한 JwtUseCase 인터페이스 추가
- JwtGenerator, JwtParser, JwtValidator, JwtUseCase 인터페이스의 구현체 추가
- HS256 알고리즘을 사용
- SecretKey 관리를 JwtConfig로 통합
- Refresh token을 Redis에 저장하는 작업은 미완성
- 작동 시간 ms 단위 저장 및 s 단위 반환 기능 구현
- JWT 토큰의 Encoded Value를 표현하기 위한 레코드 클래스 추가
- JWT 생성 로직 수정:
  - 기존 String 반환 방식에서 EncodedToken 객체 반환 방식으로 변경
  - TokenType을 사용하여 토큰 유효 기간 동적으로 설정 가능 (ACCESS_TOKEN, REFRESH_TOKEN 구분)
- 클레임(Claims) 생성 방식 개선:
  - buildClaims 메서드로 사용자 ID와 역할(role) 추가
- RefreshToken 엔티티 추가:
  - @RedisHash 어노테이션으로 Redis에 저장
  - userId(@id)를 Redis 키로 사용하여 유저별 고유 RefreshToken 관리
  - TTL(Time-to-Live) 설정: 7일
  - accessToken 갱신 메서드 추가

- 매니저 주요 기능:
  - AccessToken으로 RefreshToken 조회
  - RefreshToken 저장
  - RefreshToken 삭제 (로그아웃 구현 예정)
- RefreshTokenManager를 통해 RefreshToken 조회
- validateToken 메서드로 RefreshToken 검증
- JwtParser를 통해 AccessToken의 Claims 정보 추출
- generateAccessToken 메서드로 새로운 AccessToken 생성 및 갱신
- 갱신된 RefreshToken을 RefreshTokenManager를 통해 저장
- 주요 로직:
  - JwtGenerator를 통해 AccessToken 및 RefreshToken 생성
  - JwtValidator로 토큰 유효성 검증:
    - 유효하지 않은 경우 JwtRefresher를 통해 AccessToken 갱신
  - JwtParser로 클레임 정보 추출
@m-a-king m-a-king force-pushed the feature/29-manage-jwt branch from aa41501 to acdf448 Compare November 23, 2024 19:51
@m-a-king m-a-king changed the title [BUILD FAIL] [BUILD FAIL] [BUILD FAIL] Feature/29 JWT 기능 구현 Feature/29 JWT 기능 구현 Nov 23, 2024
@m-a-king m-a-king linked an issue Nov 23, 2024 that may be closed by this pull request
6 tasks
boolean verifyToken(String token);

String getClaimByKey(String token, String key);
} No newline at end of file
Copy link
Collaborator

Choose a reason for hiding this comment

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

마지막 라인에 경고가 나오네요 개행을 넣으면 잠재적인 에러 예방에 도움이 될 것 같아요!
https://hyeon9mak.github.io/github-no-newline-at-a-end-of-file/

Copy link
Collaborator Author

Choose a reason for hiding this comment

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

다 수정해두겠습니다!

public SecretKey secretKey(@Value("${jwt.secret}") String rawSecretKey) {
return Keys.hmacShaKeyFor(rawSecretKey.getBytes(StandardCharsets.UTF_8));
}
} No newline at end of file
Copy link
Collaborator

Choose a reason for hiding this comment

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

마지막 라인에 개행을 넣으면 좋을것 같아요

- /api/**

jwt:
secret: ${JWT_SECRET}
Copy link
Collaborator

Choose a reason for hiding this comment

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

여기도 마지막에 개행해주시면 좋을것 같습니다!

this.period = period;
}

public int getPeriodInSeconds() {
Copy link
Collaborator

Choose a reason for hiding this comment

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

메서드로 변환해주는거 깔끔하고 좋은거 같아요

Copy link
Collaborator Author

@m-a-king m-a-king Nov 24, 2024

Choose a reason for hiding this comment

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

네, ms단위는 redis에서 사용하고 s단위는 추후에 쿠키에서 사용합니다.

public int getPeriodInSeconds() {
return Math.toIntExact(period / 1000);
}
} No newline at end of file
Copy link
Collaborator

Choose a reason for hiding this comment

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

여기도 마지막줄 개행해주시면 좋을것 같습니다!

@7zrv
Copy link
Collaborator

7zrv commented Nov 24, 2024

고생하셨습니다 코드가 읽기 좋은것 같아요
혹시 Sonar가 피드백한 B등급 이슈도 나중에 설명해주신다면 좋을것 같습니다!

Copy link
Collaborator

@leebs0521 leebs0521 left a comment

Choose a reason for hiding this comment

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

고생 많으셨습니다.
잘 작성하신 코드 같아요.
몇가지 궁금한점 코멘트 드렸습니다. 답변해주시면 감사하겠습니다.

  • auth/jwt/refresh 하위에 작성된 클래스들 몇가지는 테스트가 필요해 보이는데 어떻게 생각하시는지 궁금합니다. redis에 쿼리/삽입/수정이 일어나는 클래스들이요


@Bean
public SecretKey secretKey(@Value("${jwt.secret}") String rawSecretKey) {
return Keys.hmacShaKeyFor(rawSecretKey.getBytes(StandardCharsets.UTF_8));
Copy link
Collaborator

Choose a reason for hiding this comment

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

Secretkey 빈으로 등록하는거 좋은것 같아요.

혹시 config 클래스 global/config 가 아닌 auth/jwt/config에 두신 이유가 있을까요?

Copy link
Collaborator Author

Choose a reason for hiding this comment

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

jwt에 밀접한 설정이라고 생각했습니다.
이외에도 cookieConfig, rediretConfig 와 같은 클래스들도 다 구분해뒀는데 한곳으로 모으는 게 맞을까요?

Copy link
Collaborator

Choose a reason for hiding this comment

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

말씀들어보니 맞는것 같아요 현 상태 유지해도 좋을 것 같습니다.

@RequiredArgsConstructor
@Slf4j
public class DefaultJwtRefresher implements JwtRefresher {

Copy link
Collaborator

Choose a reason for hiding this comment

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

@Transcational 없어도 괜찮을까요?
refreshAccessToken 메서드가 한 트랜잭션으로 묶여서 수행되어야 할 것 같다고 느껴져요

Copy link
Collaborator Author

Choose a reason for hiding this comment

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

JPA를 사용하지 않으므로, 더티 체킹이나 영속성 컨텍스트와 같은 개념은 적용되지 않습니다.
현재 로직을 한 단계씩 살펴보면, 조회, 검증, 파싱, 업데이트(자바 컨텍스트), 저장(레디스 컨텍스트)의 순서로 진행됩니다.

이 과정에서 실제 데이터 정합성에 영향을 미칠 수 있는 단계는 마지막 저장(레디스 컨텍스트)뿐입니다.
저장이 성공하든 실패하든, 데이터 정합성에 문제가 없다고 판단하여 트랜잭션을 사용하지 않았습니다.

Copy link
Collaborator

Choose a reason for hiding this comment

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

아 이해했습니다. 레디스에 접근하는건 그럼 조회/저장 뿐이면 괜찮아보입니다.

Copy link
Collaborator

@ayoung-dev ayoung-dev left a comment

Choose a reason for hiding this comment

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

다른 분들이 코드리뷰를 잘해주셔서 나머지는 다 좋은 거 같아요!
수고하셨습니당

@sonarqubecloud
Copy link

@m-a-king m-a-king merged commit 45bfcfd into main Nov 24, 2024
2 checks passed
@m-a-king m-a-king deleted the feature/29-manage-jwt branch November 24, 2024 10:53
m-a-king added a commit that referenced this pull request Nov 24, 2024
* feat(jwt): Add JJWT dependencies

- jjwt-api, jjwt-impl, jjwt-jackson 의존성 추가 (버전 0.12.6)

* feat(jwt): JWT 처리용 인터페이스 추가

- 토큰 생성을 위한 JwtGenerator 인터페이스 추가
- 토큰 파싱을 위한 JwtParser 인터페이스 추가
- 토큰 검증을 위한 JwtValidator 인터페이스 추가
- JWT 작업 통합을 위한 JwtUseCase 인터페이스 추가

* feat(jwt): JWT 처리용 클래스 구현 및 시크릿 키 관리 설정 추가

- JwtGenerator, JwtParser, JwtValidator, JwtUseCase 인터페이스의 구현체 추가
- HS256 알고리즘을 사용
- SecretKey 관리를 JwtConfig로 통합
- Refresh token을 Redis에 저장하는 작업은 미완성

* feat(TokenType): 토큰 타입 구분을 위한 ENUM 추가
- 작동 시간 ms 단위 저장 및 s 단위 반환 기능 구현

* feat(auth): EncodedToken 레코드 추가

- JWT 토큰의 Encoded Value를 표현하기 위한 레코드 클래스 추가

* refactor(UserRole): 패키지 이동

* feat(JwtGenerator): HmacJwtGenerator 개선 및 EncodedToken 반환 방식으로 변경

- JWT 생성 로직 수정:
  - 기존 String 반환 방식에서 EncodedToken 객체 반환 방식으로 변경
  - TokenType을 사용하여 토큰 유효 기간 동적으로 설정 가능 (ACCESS_TOKEN, REFRESH_TOKEN 구분)
- 클레임(Claims) 생성 방식 개선:
  - buildClaims 메서드로 사용자 ID와 역할(role) 추가

* feat(Jwt): 토큰 관리 방식을 String에서 EncodedToken으로 변경

* feat(RefreshToken): Redis 기반 RefreshToken 관리 기능 구현

- RefreshToken 엔티티 추가:
  - @RedisHash 어노테이션으로 Redis에 저장
  - userId(@id)를 Redis 키로 사용하여 유저별 고유 RefreshToken 관리
  - TTL(Time-to-Live) 설정: 7일
  - accessToken 갱신 메서드 추가

- 매니저 주요 기능:
  - AccessToken으로 RefreshToken 조회
  - RefreshToken 저장
  - RefreshToken 삭제 (로그아웃 구현 예정)

* feat(JwtRefresher): AccessToken 갱신 로직 추가

- RefreshTokenManager를 통해 RefreshToken 조회
- validateToken 메서드로 RefreshToken 검증
- JwtParser를 통해 AccessToken의 Claims 정보 추출
- generateAccessToken 메서드로 새로운 AccessToken 생성 및 갱신
- 갱신된 RefreshToken을 RefreshTokenManager를 통해 저장

* feat(Jwt): JWT 통합 관리 기능 추가

- 주요 로직:
  - JwtGenerator를 통해 AccessToken 및 RefreshToken 생성
  - JwtValidator로 토큰 유효성 검증:
    - 유효하지 않은 경우 JwtRefresher를 통해 AccessToken 갱신
  - JwtParser로 클레임 정보 추출

* feat(GenerateTokensOnLogin): 로그인 시 AccessToken 및 RefreshToken 생성 로직 구현

* style: delete unused import

* fix(jacocoPattern): Jwt -> jwt 오타 수정

* fix(jacocoPattern): *jwt* -> jwt/* 수정

* feat(TokenType): token period 타입 변경
- long to int

* fix(jacocoPattern): **/jwt/* -> **/jwt/**

* style: 마지막 라인 개행
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Projects

None yet

Development

Successfully merging this pull request may close these issues.

[FEATURE] JWT 기능 구현

5 participants