Skip to content

Conversation

@ohyuchan123
Copy link
Member

@ohyuchan123 ohyuchan123 commented Jan 6, 2025

πŸ“Œ κ΄€λ ¨ 이슈

#22 Jwt 둜그인 κ΅¬ν˜„

✨ 과제 λ‚΄μš©

κΈ°μ‘΄ μ„Έμ…˜ 기반 μΈμ¦μ—μ„œ JWT 기반 인증으둜 μ „ν™˜ν–ˆμŠ΅λ‹ˆλ‹€. λ³΄μ•ˆ κ°•ν™”λ₯Ό μœ„ν•΄ 토큰을
HttpOnly 쿠킀에 μ €μž₯ν•˜λŠ” 방식을 μ±„νƒν–ˆμœΌλ©°, λ‹€μŒκ³Ό 같은 λ³΄μ•ˆ 쑰치λ₯Ό μ μš©ν–ˆμŠ΅λ‹ˆλ‹€:

πŸ“Έ μŠ€ν¬λ¦°μƒ·(선택)

image

πŸ“š 레퍼런슀 (λ˜λŠ” μƒˆλ‘œ μ•Œκ²Œ 된 λ‚΄μš©) ν˜Ήμ€ κΆκΈˆν•œ 사항듀

Summary by CodeRabbit

릴리즈 λ…ΈνŠΈ

  • μƒˆλ‘œμš΄ κΈ°λŠ₯

    • JWT 기반 인증 μ‹œμŠ€ν…œ λ„μž…
    • 둜그인, λ‘œκ·Έμ•„μ›ƒ, νšŒμ›κ°€μž… μ—”λ“œν¬μΈνŠΈ μΆ”κ°€
    • λ³΄μ•ˆ κ°•ν™”λ₯Ό μœ„ν•œ 토큰 인증 λ©”μ»€λ‹ˆμ¦˜ κ΅¬ν˜„
  • κ°œμ„  사항

    • μ‚¬μš©μž 인증 ν”„λ‘œμ„ΈμŠ€ μ΅œμ ν™”
    • API λ³΄μ•ˆ μˆ˜μ€€ ν–₯상
    • μΏ ν‚€ 기반 토큰 관리 μ‹œμŠ€ν…œ ꡬ좕
  • 기술적 λ³€κ²½

    • Spring Security μ„€μ • μ—…λ°μ΄νŠΈ
    • JWT 라이브러리 μ˜μ‘΄μ„± μΆ”κ°€
    • 인증 κ΄€λ ¨ μ»΄ν¬λ„ŒνŠΈ μž¬κ΅¬μ„±

@ohyuchan123 ohyuchan123 self-assigned this Jan 6, 2025
@coderabbitai
Copy link

coderabbitai bot commented Jan 6, 2025

Walkthrough

이 ν’€ λ¦¬ν€˜μŠ€νŠΈλŠ” μ• ν”Œλ¦¬μΌ€μ΄μ…˜μ˜ 인증 및 λ³΄μ•ˆ λ©”μ»€λ‹ˆμ¦˜μ„ μ „λ©΄μ μœΌλ‘œ μž¬μ„€κ³„ν•©λ‹ˆλ‹€. JWT(JSON Web Token) 기반 인증 μ‹œμŠ€ν…œμ„ λ„μž…ν•˜μ—¬ μ‚¬μš©μž 둜그인, λ‘œκ·Έμ•„μ›ƒ, 등둝 ν”„λ‘œμ„ΈμŠ€λ₯Ό κ°œμ„ ν•©λ‹ˆλ‹€. μƒˆλ‘œμš΄ λ³΄μ•ˆ ꡬ성, 인증 ν•„ν„°, 토큰 μœ ν‹Έλ¦¬ν‹° 클래슀λ₯Ό μΆ”κ°€ν•˜κ³  κΈ°μ‘΄ 등둝 κ΄€λ ¨ μ»΄ν¬λ„ŒνŠΈλ₯Ό λ¦¬νŒ©ν† λ§ν•˜μ—¬ λ”μš± μ•ˆμ „ν•˜κ³  효율적인 인증 λ©”μ»€λ‹ˆμ¦˜μ„ κ΅¬ν˜„ν•©λ‹ˆλ‹€.

Changes

파일 λ³€κ²½ μš”μ•½
build.gradle JWT κ΄€λ ¨ μ˜μ‘΄μ„± 3개 μΆ”κ°€
SecurityConfig.java JWT ν•„ν„° 및 인증 μ„€μ • μ—…λ°μ΄νŠΈ
AuthController.java μƒˆλ‘œμš΄ 인증 컨트둀러 생성
LoginRequestDto.java 둜그인 μš”μ²­ DTO μΆ”κ°€
LoginResponseDto.java 둜그인 응닡 DTO μΆ”κ°€
JWTFilter.java JWT 인증 ν•„ν„° κ΅¬ν˜„
JWTUtil.java JWT 토큰 생성 및 검증 μœ ν‹Έλ¦¬ν‹° 클래슀 μΆ”κ°€

Sequence Diagram

sequenceDiagram
    participant Client
    participant AuthController
    participant AuthService
    participant JWTUtil
    participant MemberRepository

    Client->>AuthController: 둜그인 μš”μ²­
    AuthController->>AuthService: login(credentials)
    AuthService->>MemberRepository: findByEmail()
    MemberRepository-->>AuthService: Member
    AuthService->>JWTUtil: createToken(email)
    JWTUtil-->>AuthService: JWT 토큰
    AuthService-->>AuthController: 둜그인 응닡
    AuthController-->>Client: JWT μΏ ν‚€ 및 μ‚¬μš©μž 정보
Loading

Possibly related PRs

Suggested labels

βœ… Test, πŸ”¨ Refactor, ✨ Feature

Poem

🐰 ν† ν°μ˜ 토끼, λ³΄μ•ˆμ„ 달리닀
JWT의 길을 μ—΄μ–΄μ –νžˆλ‹ˆ
μΏ ν‚€λŠ” 반짝이고, 인증은 μΆ€μΆ”λ„€
λ³΄μ•ˆμ˜ 문을 ν™œμ§ μ—΄μ–΄μ –νžˆλŠ”
우리의 μž‘μ€ μ½”λ“œ λ§ˆλ²•! πŸ”βœ¨


πŸͺ§ Tips

Chat

There are 3 ways to chat with CodeRabbit:

  • Review comments: Directly reply to a review comment made by CodeRabbit. Example:
    • I pushed a fix in commit <commit_id>, please review it.
    • Generate unit testing code for this file.
    • Open a follow-up GitHub issue for this discussion.
  • Files and specific lines of code (under the "Files changed" tab): Tag @coderabbitai in a new review comment at the desired location with your query. Examples:
    • @coderabbitai generate unit testing code for this file.
    • @coderabbitai modularize this function.
  • PR comments: Tag @coderabbitai in a new PR comment to ask questions about the PR branch. For the best results, please provide a very specific query, as very limited context is provided in this mode. Examples:
    • @coderabbitai gather interesting stats about this repository and render them as a table. Additionally, render a pie chart showing the language distribution in the codebase.
    • @coderabbitai read src/utils.ts and generate unit testing code.
    • @coderabbitai read the files in the src/scheduler package and generate a class diagram using mermaid and a README in the markdown format.
    • @coderabbitai help me debug CodeRabbit configuration file.

Note: Be mindful of the bot's finite context window. It's strongly recommended to break down tasks such as reading entire modules into smaller chunks. For a focused discussion, use review comments to chat about specific files and their changes, instead of using the PR comments.

CodeRabbit Commands (Invoked using PR comments)

  • @coderabbitai pause to pause the reviews on a PR.
  • @coderabbitai resume to resume the paused reviews.
  • @coderabbitai review to trigger an incremental review. This is useful when automatic reviews are disabled for the repository.
  • @coderabbitai full review to do a full review from scratch and review all the files again.
  • @coderabbitai summary to regenerate the summary of the PR.
  • @coderabbitai generate docstrings to generate docstrings for this PR. (Beta)
  • @coderabbitai resolve resolve all the CodeRabbit review comments.
  • @coderabbitai configuration to show the current CodeRabbit configuration for the repository.
  • @coderabbitai help to get help.

Other keywords and placeholders

  • Add @coderabbitai ignore anywhere in the PR description to prevent this PR from being reviewed.
  • Add @coderabbitai summary to generate the high-level summary at a specific location in the PR description.
  • Add @coderabbitai anywhere in the PR title to generate the title automatically.

Documentation and Community

  • Visit our Documentation for detailed information on how to use CodeRabbit.
  • Join our Discord Community to get help, request features, and share feedback.
  • Follow us on X/Twitter for updates and announcements.

Copy link

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

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

Actionable comments posted: 3

🧹 Nitpick comments (20)
src/main/java/com/mycom/socket/auth/config/SecurityConfig.java (2)

28-28: [CORS μ„€μ • μœ μ—°μ„± μ œμ•ˆ]

applyPermitDefaultValues()λŠ” νŽΈλ¦¬ν•˜μ§€λ§Œ, ν”„λ‘œλ•μ…˜ ν™˜κ²½μ—μ„œλŠ” 도메인 및 λ©”μ„œλ“œ μ œμ•½μ„ μ’€ 더 μ„Έλ°€ν•˜κ²Œ κ΅¬μ„±ν•˜λŠ” 것이 μ•ˆμ „ν•©λ‹ˆλ‹€. ν•„μš”μ— 따라 CORS 섀정을 κ΅¬μ²΄ν™”ν•˜λŠ” λ°©μ•ˆμ„ κ³ λ €ν•΄ λ³΄μ„Έμš”.


40-40: [μ—”λ“œν¬μΈνŠΈ μ ‘κ·Ό κΆŒν•œ κ²€ν† ]

"/","/api/auth/**", "/swagger-ui/**", "/v3/api-docs/**" κ²½λ‘œμ— λŒ€ν•œ permitAll()은 νŽΈμ˜μ„± λ©΄μ—μ„œλŠ” μœ μ΅ν•˜μ§€λ§Œ, λ―Όκ°ν•œ API λ¬Έμ„œλŠ” 운영 ν™˜κ²½μ—μ„œ 접근을 μ œν•œν•΄μ•Ό ν•  μˆ˜λ„ μžˆμŠ΅λ‹ˆλ‹€. ν•„μš” μ‹œ λ³΄μ•ˆ 정책을 μž¬κ²€ν† ν•΄ λ³΄μ„Έμš”.

src/main/java/com/mycom/socket/auth/jwt/JWTFilter.java (1)

24-49: [JWT 토큰 검증 둜직]

doFilterInternal λ©”μ„œλ“œμ—μ„œ 쿠킀에 λ‹΄κΈ΄ 토큰을 νŒŒμ‹±ν•˜κ³ , 토큰 μœ νš¨μ„± 검증 ν›„ SecurityContextHolder에 인증 정보λ₯Ό μ €μž₯ν•˜λŠ” 흐름이 μ΄μƒμ μž…λ‹ˆλ‹€.

  • 토큰이 μœ νš¨ν•˜μ§€ μ•Šμ€ 경우의 μ˜ˆμ™Έ μ²˜λ¦¬κ°€ κ°„λ‹¨ν•˜κ²Œ clearContext()둜 μ²˜λ¦¬λ˜λŠ”λ°, ν•„μš”ν•˜λ‹€λ©΄ 디버깅 μš©λ„ λ‘œκΉ…μ„ μΆ”κ°€ν•΄μ„œ λ³΄μ•ˆ 이벀트 λͺ¨λ‹ˆν„°λ§μ„ κ°•ν™”ν•  수 μžˆμŠ΅λ‹ˆλ‹€.
src/main/java/com/mycom/socket/auth/service/MemberDetailsService.java (1)

19-21: [KO] μ˜ˆμ™Έ λ©”μ‹œμ§€λ₯Ό ꡬ체적으둜 μž‘μ„±ν•΄μ£Όμ„Έμš”.
"μ‚¬μš©μžλ₯Ό 찾을 수 μ—†μŠ΅λ‹ˆλ‹€." λΌλŠ” λ©”μ‹œμ§€ λŒ€μ‹ , μ‚¬μš©μžμ˜ 이메일 정보 등을 ν¬ν•¨ν•˜λ©΄ 디버깅과 λ‘œκΉ…μ— μ’€ 더 μœ μš©ν•©λ‹ˆλ‹€.

-orElseThrow(() -> new UsernameNotFoundException("μ‚¬μš©μžλ₯Ό 찾을 수 μ—†μŠ΅λ‹ˆλ‹€."))
+orElseThrow(() -> new UsernameNotFoundException("ν•΄λ‹Ή 이메일(" + email + ")에 ν•΄λ‹Ήν•˜λŠ” μ‚¬μš©μžλ₯Ό 찾을 수 μ—†μŠ΅λ‹ˆλ‹€."))
src/main/java/com/mycom/socket/auth/controller/AuthController.java (1)

28-31: [KO] λ‘œκ·Έμ•„μ›ƒ 둜직 보강 μ œμ•ˆ
ν˜„μž¬ λ‘œκ·Έμ•„μ›ƒ μ‹œ μΏ ν‚€μ˜ JWT ν† ν°λ§Œ λ§Œλ£Œμ‹œν‚€λŠ”μ§€ μ—¬λΆ€κ°€ κΆκΈˆν•©λ‹ˆλ‹€. μ„Έμ…˜ 관리λ₯Ό λ³‘ν–‰ν•˜κ±°λ‚˜ Redis 같은 인메λͺ¨λ¦¬ μ„œλΉ„μŠ€λ₯Ό ν™œμš©ν•˜λŠ” 방식도 κ³ λ €ν•΄ λ³Ό 수 μžˆμŠ΅λ‹ˆλ‹€.

src/main/java/com/mycom/socket/auth/security/MemberDetails.java (1)

37-55: [KO] 계정 μƒνƒœ ν”Œλž˜κ·Έ 확인 ν•„μš”
ν˜„μž¬ isAccountNonExpired(), isAccountNonLocked(), isCredentialsNonExpired(), isEnabled()κ°€ μ „λΆ€ trueλ₯Ό λ°˜ν™˜ν•˜κ³  μžˆμŠ΅λ‹ˆλ‹€. 이 값듀을 멀버 ν•„λ“œλ‘œ 관리할 κ³„νšμ΄ μžˆλ‹€λ©΄, μΆ”ν›„ ν™•μž₯에 λŒ€λΉ„ν•΄ getter λ©”μ†Œλ“œλ₯Ό λ³„λ„λ‘œ μ§€μ›ν•˜λŠ” λ°©μ•ˆμ„ κ³ λ―Όν•΄ λ³Ό 수 μžˆμŠ΅λ‹ˆλ‹€.

src/main/java/com/mycom/socket/auth/jwt/JWTUtil.java (1)

22-35: [KO] 토큰 λ§Œλ£Œμ‹œκ°„ μƒμˆ˜ν™” ꢌμž₯
30λΆ„μ΄λΌλŠ” 만료 μ‹œκ°„ 값을 μ½”λ“œ 내에 직접 λ„£κΈ°λ³΄λ‹€λŠ” μƒμˆ˜λ‚˜ μ„€μ • 파일둜 λΆ„λ¦¬ν•˜μ—¬ μœ μ§€λ³΄μˆ˜μ— μœ λ¦¬ν•˜κ²Œ λ§Œλ“œλŠ” 것을 ꢌμž₯ν•©λ‹ˆλ‹€.

- long accessTokenValidityInMilliseconds = 1000 * 60 * 30;
+ private static final long ACCESS_TOKEN_VALIDITY_MS = 1000 * 60 * 30;
...
long accessTokenValidityInMilliseconds = ACCESS_TOKEN_VALIDITY_MS;
src/test/java/com/mycom/socket/member/service/RegisterServiceTest.java (2)

25-25: [KO] ν…ŒμŠ€νŠΈ 클래슀 λͺ…κ³Ό μ‹€μ œ λŒ€μƒ κΈ°λŠ₯의 일치
RegisterServiceTest λΌλŠ” 클래슀λͺ…κ³Ό 달리, μ‹€μ œ ν…ŒμŠ€νŠΈλŠ” AuthServiceλ₯Ό μ£Όμž…λ°›μ•„ 등둝 κΈ°λŠ₯을 ν…ŒμŠ€νŠΈν•˜κ³  μžˆμŠ΅λ‹ˆλ‹€. μΆ”ν›„ ν˜Όλ™ λ°©μ§€λ₯Ό μœ„ν•΄ AuthServiceRegisterTest λ“± 더 직관적인 클래슀λͺ…μœΌλ‘œ 변경을 κ³ λ €ν•΄λ³Ό 수 μžˆμŠ΅λ‹ˆλ‹€.


Line range hint 36-60: [KO] ν…ŒμŠ€νŠΈμ—μ„œ 쀑볡 검사 둜직 μΆ”κ°€ 확인
이 λ©”μ„œλ“œμ—μ„œ 이메일과 λ‹‰λ„€μž„μ— λŒ€ν•œ 쀑볡 검사λ₯Ό ν…ŒμŠ€νŠΈν•˜κ³  μžˆμ§€λ§Œ, 쀑볡 λ°œμƒ μ‹œ μ˜ˆμ™Έλ₯Ό λ˜μ§€λŠ”μ§€, μ–΄λŠ λ ˆλ²¨μ—μ„œ μ˜ˆμ™Έκ°€ μ²˜λ¦¬λ˜λŠ”μ§€ λͺ…ν™•ν•œ 검증이 ν•„μš”ν•΄ λ³΄μž…λ‹ˆλ‹€. μ˜ˆμ™Έ 상황 ν…ŒμŠ€νŠΈ(existsByEmail ν˜Ήμ€ existsByNickname이 true일 경우)에 λŒ€ν•œ λ‹¨μœ„ ν…ŒμŠ€νŠΈλ„ ν•¨κ»˜ μ œκ³΅ν•˜λ©΄ μ’‹μŠ΅λ‹ˆλ‹€.

src/test/java/com/mycom/socket/member/service/LoginIntegrationTest.java (2)

36-44: ν…ŒμŠ€νŠΈ 멀버 μ΄ˆκΈ°ν™” 둜직 점검 ν•„μš”
ν…ŒμŠ€νŠΈ μ‹œμž‘ μ „ 멀버λ₯Ό 맀번 μƒˆλ‘œ μ €μž₯ν•˜λ―€λ‘œ, 동일 μ΄λ©”μΌλ‘œ μΈν•œ μ˜ˆμ™Έ 상황 ν…ŒμŠ€νŠΈλ₯Ό κ³ λ €ν•  μˆ˜λ„ μžˆμŠ΅λ‹ˆλ‹€. ν•„μš”ν•˜λ‹€λ©΄ @BeforeEachμ—μ„œ 이미 μ‘΄μž¬ν•˜λŠ” 이메일 상황을 ν…ŒμŠ€νŠΈ μΌ€μ΄μŠ€λ‘œ 뢄리해볼 수 μžˆμŠ΅λ‹ˆλ‹€.


54-65: μΏ ν‚€ 섀정에 λŒ€ν•œ λ³΄μ•ˆ 점검
ν…ŒμŠ€νŠΈμ—μ„œ Authorization μΏ ν‚€κ°€ HTTP-Only이자 Secure ν”Œλž˜κ·Έκ°€ μ„€μ •λ˜μ–΄ 30λΆ„ μœ νš¨κΈ°κ°„μœΌλ‘œ κ²€μ¦λ˜λŠ” 점은 μ’‹μŠ΅λ‹ˆλ‹€. λ‹€λ§Œ, 도메인 섀정이 ν•„μš”ν•˜λ‹€λ©΄ κ°•ν™”ν•˜μ—¬ λ³΄μ•ˆμ„±μ„ 높일 수 μžˆμœΌλ‹ˆ, 도메인도 λͺ…μ‹œ μ„€μ •ν•˜λŠ” λ°©μ•ˆμ„ κ³ λ €ν•΄ λ³Ό 수 μžˆμŠ΅λ‹ˆλ‹€.

src/test/java/com/mycom/socket/member/controller/RegisterControllerTest.java (2)

34-34: AuthService에 λŒ€ν•œ MockBean ꡬ성 확인
AuthServiceλ₯Ό 컨트둀러 ν…ŒμŠ€νŠΈμš©μœΌλ‘œ MockBean μ²˜λ¦¬ν•˜λŠ” 것은 μ μ ˆν•©λ‹ˆλ‹€. λ‹€λ§Œ, νšŒμ›κ°€μž… 외에 둜그인 κΈ°λŠ₯ λ“± λ‹€λ₯Έ λ©”μ„œλ“œλ₯Ό ν˜ΈμΆœν•˜μ§€λŠ” μ•ŠλŠ”μ§€ ν™•μΈν•˜κ³ , ν•„μš” μ‹œ λ³„λ„μ˜ ν…ŒμŠ€νŠΈλ₯Ό μœ„ν•΄ Mock λ™μž‘μ„ λΆ„λ¦¬ν•΄λ‘λŠ” 것도 도움이 될 수 μžˆμŠ΅λ‹ˆλ‹€.


40-46: νšŒμ›κ°€μž… 성곡 ν…ŒμŠ€νŠΈ μΌ€μ΄μŠ€ λ‘œκΉ…
νšŒμ›κ°€μž… 성곡 μ‹œ, λ°˜ν™˜λ˜λŠ” idκ°€ μ˜¬λ°”λ₯Έμ§€ μ—¬λΆ€λ§Œ ν™•μΈν•˜κ³  μžˆμŠ΅λ‹ˆλ‹€. μΆ”κ°€λ‘œ 이메일 쀑볡 체크, λ‹‰λ„€μž„ 쀑볡 체크 λ“±μ˜ λ‚΄λΆ€ 둜직이 정상 ν˜ΈμΆœλ˜μ—ˆλŠ”μ§€ Mockitoλ₯Ό 톡해 μ’€ 더 μ„ΈλΆ€ 검증해볼 μˆ˜λ„ μžˆμŠ΅λ‹ˆλ‹€.

src/main/java/com/mycom/socket/auth/service/AuthService.java (3)

28-34: 둜그인 둜직 μ˜ˆμ™Έ 처리 보완
BadRequestException μ‚¬μš©μœΌλ‘œ 이메일 미등둝, λΉ„λ°€λ²ˆν˜Έ 뢈일치 상황을 μ²˜λ¦¬ν•˜κ³  μžˆμŠ΅λ‹ˆλ‹€. λ³΄μ•ˆμƒ, 동일 λ©”μ‹œμ§€λ₯Ό λ°˜ν™˜ν•˜κ±°λ‚˜ νŠΉμ • 상황별 μ»€μŠ€ν…€ μ˜ˆμ™Έλ₯Ό λΆ„λ¦¬ν•˜λŠ” 방법도 μžˆμŠ΅λ‹ˆλ‹€. λ§Œμ•½ λ³΄μ•ˆμ„ κ°•ν™”ν•˜κ³  μ‹Άλ‹€λ©΄, "잘λͺ»λœ 이메일 ν˜Ήμ€ λΉ„λ°€λ²ˆν˜Έ"둜 ν†΅ν•©ν•˜μ—¬ κ³΅κ²©μžκ°€ 정보λ₯Ό μΆ”λ‘ ν•˜κΈ° μ–΄λ ΅κ²Œ ν•  수 μžˆμŠ΅λ‹ˆλ‹€.


36-46: JWT 토큰 생성 μ‹œμ μ— λŒ€ν•œ 주의
둜그인 μ‹œ λ°”λ‘œ μΏ ν‚€λ₯Ό μ„€μ •ν•΄μ£Όκ³  μžˆμŠ΅λ‹ˆλ‹€. 토큰 κ°±μ‹ (refresh) λ˜λŠ” μ„Έμ…˜ 만료 둜직이 ν•„μš”ν•œ 경우 이 뢀뢄이 μ—°κ³„λ˜μ–΄μ•Ό ν•˜λ―€λ‘œ, μΆ”ν›„ ν™•μž₯에 λŒ€λΉ„ν•΄ λ‘œμ§μ„ 뢄리(예: createCookieWithToken λ©”μ„œλ“œ λ“±)ν•˜λ©΄ μœ μ§€λ³΄μˆ˜μ— μš©μ΄ν•©λ‹ˆλ‹€.


57-66: νšŒμ›κ°€μž… 쀑볡 검사 둜직 μ„ΈλΆ„ν™”
이메일, λ‹‰λ„€μž„ 쀑볡을 κ°œλ³„μ μœΌλ‘œ κ²€μ‚¬ν•˜κ³  μžˆλŠ”λ°, μ˜ˆμ™Έμ²˜λ¦¬λ₯Ό λΆ„λ¦¬ν•œ 뢀뢄은 λͺ…ν™•ν•©λ‹ˆλ‹€. 비동기 ν™˜κ²½μ—μ„œ 두 쑰건을 λ™μ‹œμ— λ§Œμ‘±ν•˜μ§€ μ•ŠλŠ” 경쟁 쑰건이 λ°œμƒν•  수 μžˆμœΌλ―€λ‘œ, DB λ ˆλ²¨μ—μ„œ Unique Indexλ₯Ό 톡해 μ΅œμ’…μ μœΌλ‘œ λ³΄ν˜Έν•˜λŠ”μ§€ ν•¨κ»˜ ν™•μΈλ°”λžλ‹ˆλ‹€.

src/main/java/com/mycom/socket/auth/security/LoginFilter.java (2)

31-45: 둜그인 μš”μ²­ 처리 μ—λŸ¬ λ©”μ‹œμ§€ μ„ΈλΆ„ν™”
RuntimeException으둜 λ¬Άμ–΄μ„œ λ˜μ§€λŠ” λŒ€μ‹ , λͺ…ν™•ν•œ μ»€μŠ€ν…€ μ˜ˆμ™Έλ‚˜ λ‹€λ₯Έ μ˜ˆμ™Έ ꡬ뢄 방식을 λ„μž…ν•  수 μžˆμŠ΅λ‹ˆλ‹€. JSON νŒŒμ‹± 문제 λ“± 상세 원인 νŒŒμ•…μ΄ ν•„μš”ν•  λ•Œ, λ‘œκ·Έμ—μ„œ 좔적이 μ‰½κ²Œ λ˜λ„λ‘ μ˜ˆμ™Έ νƒ€μž…μ„ μ„ΈλΆ„ν™”ν•˜μ„Έμš”.


74-83: 둜그인 μ‹€νŒ¨ 처리
둜그인 μ‹€νŒ¨ μ‹œ 401을 λ°˜ν™˜ν•˜κ³  있으며, "λ‘œκ·ΈμΈμ— μ‹€νŒ¨ν–ˆμŠ΅λ‹ˆλ‹€. 이메일 λ˜λŠ” λΉ„λ°€λ²ˆν˜Έλ₯Ό ν™•μΈν•΄μ£Όμ„Έμš”."λΌλŠ” λ©”μ‹œμ§€κ°€ 좜λ ₯λ©λ‹ˆλ‹€. 인증 μ‹€νŒ¨ λ‘œκΉ…μ΄λ‚˜ λ³΄μ•ˆ λͺ¨λ‹ˆν„°λ§ 체계λ₯Ό κ΅¬μΆ•ν•˜λ €λ©΄, 좔가적인 둜그 기둝(원격 IP, μ‹œλ„ 횟수) 등이 ν•„μš”ν•  수 μžˆμŠ΅λ‹ˆλ‹€.

src/test/java/com/mycom/socket/member/service/LoginTest.java (2)

90-103: 이메일 미쑴재 μ˜ˆμ™Έ 흐름 검증
이메일이 μ‘΄μž¬ν•˜μ§€ μ•Šμ„ λ•Œ BadRequestException을 던져 μ •ν™•νžˆ κ²€μ¦ν•˜λŠ” 점은 μ’‹μŠ΅λ‹ˆλ‹€. κ·ΈλŸ¬λ‚˜ UI UX μΈ‘λ©΄μ—μ„œ 이메일 ν˜Ήμ€ λΉ„λ°€λ²ˆν˜Έκ°€ 틀렸을 λ•Œ λ™μΌν•œ λ©”μ‹œμ§€λ₯Ό λ°˜ν™˜ν• μ§€ 뢄리할지 νŒ€ 정책을 μž¬κ²€ν† ν•΄λ³Ό μˆ˜λ„ μžˆμŠ΅λ‹ˆλ‹€.


105-128: λΉ„λ°€λ²ˆν˜Έ 뢈일치 μ˜ˆμ™Έ 처리 점검
λΉ„λ°€λ²ˆν˜Έκ°€ 틀릴 경우 μ˜ˆμ™Έ λ°œμƒ ν›„ μΏ ν‚€κ°€ μƒμ„±λ˜μ§€ μ•ŠλŠ” μ‹œλ‚˜λ¦¬μ˜€ 확인이 μ μ ˆν•©λ‹ˆλ‹€. λ‹€λ§Œ, μ†Œμ…œ 둜그인 λ“± 별도 인증체계가 λ„μž…λ  κ²½μš°μ—λ„ 동일 λ‘œμ§μ„ μž¬ν™œμš©ν•  수 μžˆλŠ”μ§€ ν™•μΈν•˜μ—¬, AuthService의 ꡬ쑰λ₯Ό ν™•μž₯μ„± 있게 μœ μ§€ν•˜μ‹œκΈΈ ꢌμž₯ν•©λ‹ˆλ‹€.

πŸ“œ Review details

Configuration used: .coderabbit.yaml
Review profile: CHILL
Plan: Pro

πŸ“₯ Commits

Reviewing files that changed from the base of the PR and between 793fecb and 4ce724a.

πŸ“’ Files selected for processing (19)
  • build.gradle (1 hunks)
  • src/main/java/com/mycom/socket/auth/config/SecurityConfig.java (2 hunks)
  • src/main/java/com/mycom/socket/auth/controller/AuthController.java (1 hunks)
  • src/main/java/com/mycom/socket/auth/dto/request/LoginRequestDto.java (1 hunks)
  • src/main/java/com/mycom/socket/auth/dto/request/RegisterRequestDto.java (1 hunks)
  • src/main/java/com/mycom/socket/auth/dto/response/LoginResponseDto.java (1 hunks)
  • src/main/java/com/mycom/socket/auth/jwt/JWTFilter.java (1 hunks)
  • src/main/java/com/mycom/socket/auth/jwt/JWTUtil.java (1 hunks)
  • src/main/java/com/mycom/socket/auth/security/LoginFilter.java (1 hunks)
  • src/main/java/com/mycom/socket/auth/security/MemberDetails.java (1 hunks)
  • src/main/java/com/mycom/socket/auth/service/AuthService.java (1 hunks)
  • src/main/java/com/mycom/socket/auth/service/MemberDetailsService.java (1 hunks)
  • src/main/java/com/mycom/socket/go_socket/controller/RegisterController.java (0 hunks)
  • src/main/java/com/mycom/socket/go_socket/repository/MemberRepository.java (1 hunks)
  • src/main/java/com/mycom/socket/go_socket/service/RegisterService.java (0 hunks)
  • src/test/java/com/mycom/socket/member/controller/RegisterControllerTest.java (4 hunks)
  • src/test/java/com/mycom/socket/member/service/LoginIntegrationTest.java (1 hunks)
  • src/test/java/com/mycom/socket/member/service/LoginTest.java (1 hunks)
  • src/test/java/com/mycom/socket/member/service/RegisterServiceTest.java (4 hunks)
πŸ’€ Files with no reviewable changes (2)
  • src/main/java/com/mycom/socket/go_socket/service/RegisterService.java
  • src/main/java/com/mycom/socket/go_socket/controller/RegisterController.java
βœ… Files skipped from review due to trivial changes (1)
  • src/main/java/com/mycom/socket/auth/dto/request/RegisterRequestDto.java
πŸ”‡ Additional comments (19)
src/main/java/com/mycom/socket/auth/config/SecurityConfig.java (3)

3-5: [μž„ν¬νŠΈ μΆ”κ°€ 사항]

JWT κ΄€λ ¨ 클래슀(JWTFilter, JWTUtil, MemberDetailsService)λ₯Ό μž„ν¬νŠΈν•˜λŠ” κ΅¬λ¬Έμž…λ‹ˆλ‹€. JWT 기반 인증 흐름에 ν•„μš”ν•œ μ»΄ν¬λ„ŒνŠΈλ“€μ΄ 적절히 κ΅¬μ„±λœ κ²ƒμœΌλ‘œ λ³΄μž…λ‹ˆλ‹€. μŠ€ν”„λ§ μ‹œνλ¦¬ν‹° ν•„ν„°(UsernamePasswordAuthenticationFilter)λ₯Ό ν™•μž₯/λ³΄μ™„ν•˜κΈ° μœ„ν•œ μž„ν¬νŠΈλ„ 문제 μ—†μ–΄ λ³΄μž…λ‹ˆλ‹€.

Also applies to: 14-14


22-23: [μ£Όμž… ν•„λ“œ 확인]

private final ν•„λ“œ 선언을 톡해 μƒμ„±μž μ£Όμž…(@requiredargsconstructor)을 μ‚¬μš©ν•˜λŠ” κ΅¬μ„±μž…λ‹ˆλ‹€. jwtUtilκ³Ό memberDetailsServiceκ°€ μ •μƒμ μœΌλ‘œ DI λ˜μ–΄ μ‚¬μš©λ˜λ„λ‘, ν™˜κ²½ κ΅¬μ„±μ΄λ‚˜ 빈 등둝에 λˆ„λ½λœ 뢀뢄이 μ—†λŠ”μ§€ μ΅œμ’… ν™•μΈν•΄μ£Όμ„Έμš”.


33-33: [JWT ν•„ν„° 체인 μ„€μ •]

UsernamePasswordAuthenticationFilter 이전에 JWTFilterλ₯Ό 두어 μΏ ν‚€ 기반 JWT 검증을 μ‹€ν–‰ν•˜λŠ” 것은 μ μ ˆν•œ μ ‘κ·Όμž…λ‹ˆλ‹€. λ‹€λ§Œ, JWTFilterμ—μ„œ μ˜ˆμ™Έ λ°œμƒ μ‹œ μΆ©λΆ„ν•œ λ‘œκΉ… 및 μ—λŸ¬ μ²˜λ¦¬κ°€ μ΄λ£¨μ–΄μ§€λŠ”μ§€ ν•¨κ»˜ 점검해 μ£Όμ„Έμš”.

src/main/java/com/mycom/socket/auth/jwt/JWTFilter.java (3)

18-19: [클래슀 μ„ μ–Έ 및 둬볡 μ„€μ •]

@RequiredArgsConstructorλ₯Ό 톡해 ν•„μš”ν•œ μ˜μ‘΄μ„±μ„ μƒμ„±μž μ£Όμž… λ°›λŠ” κ΅¬μ‘°λŠ” κ°„κ²°ν•˜κ³  μœ μ§€λ³΄μˆ˜μ— μš©μ΄ν•©λ‹ˆλ‹€.


21-23: [JWT κ΄€λ ¨ ν•„λ“œ]

jwtUtilκ³Ό memberDetailsService ν•„λ“œκ°€ JWT 토큰 검증과 μ‚¬μš©μž 정보 λ‘œλ”©μ— μ‚¬μš©λ©λ‹ˆλ‹€. λͺ…ν™•ν•œ μ±…μž„ λΆ„λ¦¬λ‘œ ν•„ν„° λ‚΄μ—μ„œ 인증 절차λ₯Ό μ§κ΄€μ μœΌλ‘œ μ²˜λ¦¬ν•  수 μžˆμ–΄ λ³΄μž…λ‹ˆλ‹€.


51-61: [μΏ ν‚€μ—μ„œ 토큰 μΆ”μΆœ 둜직]

"Authorization" μ΄λ¦„μ˜ μΏ ν‚€λ₯Ό νƒμƒ‰ν•˜μ—¬ 토큰을 μΆ”μΆœν•˜λŠ” 뢀뢄은 κ°„λ‹¨ν•˜κ³  λͺ…ν™•ν•©λ‹ˆλ‹€. λ³΄μ•ˆ κ°•ν™”λ₯Ό μœ„ν•΄ μΏ ν‚€ μ„€μ •(예: HttpOnly, Secure μ˜΅μ…˜)이 ν•¨κ»˜ μ μš©λ˜μ–΄ μžˆλŠ”μ§€ 확인해 λ³΄μ„Έμš”.

src/main/java/com/mycom/socket/auth/dto/response/LoginResponseDto.java (1)

1-10: [둜그인 응닡 DTO]

record ꡬ문으둜 μ΅œμ†Œν•œμ˜ μ½”λ“œλ‘œ DTOλ₯Ό κ΅¬μ„±ν•œ 점이 κ°„κ²°ν•˜κ³  μ’‹μŠ΅λ‹ˆλ‹€. of 정적 νŒ©ν† λ¦¬ λ©”μ„œλ“œλ₯Ό ν™œμš©ν•΄ λͺ…ν™•ν•˜κ²Œ 객체λ₯Ό 생성할 수 μžˆμ–΄ μœ μ§€λ³΄μˆ˜ 츑면에도 μœ λ¦¬ν•©λ‹ˆλ‹€.

src/main/java/com/mycom/socket/auth/dto/request/LoginRequestDto.java (1)

3-13: [둜그인 μš”μ²­ 검증]

@NotBlank와 @Email을 톡해 이메일 ν˜•μ‹κ³Ό 곡백 검증을 μˆ˜ν–‰ν•˜λŠ” 점이 μ μ ˆν•©λ‹ˆλ‹€. 잘λͺ»λœ ν˜•μ‹μ΄ λ“€μ–΄μ˜¬ λ•Œ μžλ™μœΌλ‘œ μ˜ˆμ™Έκ°€ λ°œμƒν•˜λ―€λ‘œ, API μ‚¬μš©μ„± 및 λ³΄μ•ˆ λ©΄μ—μ„œ μœ λ¦¬ν•©λ‹ˆλ‹€.

src/main/java/com/mycom/socket/go_socket/repository/MemberRepository.java (1)

6-7: [이메일 기반 쑰회 λ©”μ„œλ“œ μΆ”κ°€]

Optional<Member> findByEmail(String email) λ©”μ„œλ“œλ₯Ό μΆ”κ°€ν•˜μ—¬ νšŒμ› 검색 κΈ°λŠ₯이 ν™•μž₯λ˜μ—ˆμŠ΅λ‹ˆλ‹€. 이λ₯Ό 톡해 이메일을 ν†΅ν•œ 인증 및 μ‚¬μš©μž 정보 μ‘°νšŒκ°€ λ”μš± λͺ…ν™•ν•΄μ§ˆ κ²ƒμœΌλ‘œ λ³΄μž…λ‹ˆλ‹€.

Also applies to: 11-11

src/main/java/com/mycom/socket/auth/service/MemberDetailsService.java (1)

16-16: [KO] μ„œλΉ„μŠ€ μ£Όμž… 방식을 ν™•μΈν•΄μ£Όμ„Έμš”.
memberRepositoryκ°€ @RequiredArgsConstructor둜 μ£Όμž…λ˜κ³  μžˆμœΌλ―€λ‘œ, λ‹€λ₯Έ μ˜μ‘΄μ„±λ„ λͺ¨λ‘ λ™μΌν•œ Lombok λ°©μ‹μœΌλ‘œ μ£Όμž…ν•˜λŠ” 것이 일관성 μœ μ§€μ— μ’‹μŠ΅λ‹ˆλ‹€.

src/main/java/com/mycom/socket/auth/controller/AuthController.java (2)

20-25: [KO] 둜그인 API λ°˜ν™˜ νƒ€μž…κ³Ό κ΅¬ν˜„μ„ ν™•μΈν•΄μ£Όμ„Έμš”.
authService.login(request, response)κ°€ LoginResponseDtoλ₯Ό λ°˜ν™˜ν•˜κ³  μžˆλŠ”λ°, μ˜ˆμ™Έ 상황 ν˜Ήμ€ μœ νš¨μ„± 검증 μ‹€νŒ¨ μ‹œ μ–΄λ–€ 처리λ₯Ό ν•˜λŠ”μ§€ κ²€ν† κ°€ ν•„μš”ν•©λ‹ˆλ‹€. Springμ—μ„œ λ°œμƒν•  수 μžˆλŠ” MethodArgumentNotValidException을 μ²˜λ¦¬ν•  κΈ€λ‘œλ²Œ μ˜ˆμ™Έ μ²˜λ¦¬κ°€ ν•¨κ»˜ κ΅¬ν˜„λ˜μ–΄ μžˆλŠ”μ§€λ„ ν™•μΈν•΄μ£Όμ„Έμš”.


33-36: [KO] νšŒμ›κ°€μž… μ‹œ μ˜ˆμ™Έ 처리 둜직 확인 ν•„μš”
νšŒμ›κ°€μž… 쀑볡 κ²€μ‚¬μ—μ„œ λ°œμƒν•˜λŠ” μ˜ˆμ™Έλ‚˜, λΉ„λ°€λ²ˆν˜Έ μ •μ±… μœ„λ°˜μ˜ 경우 등을 μ–΄λ–»κ²Œ μ²˜λ¦¬ν•˜κ³  μžˆλŠ”μ§€ 확인이 ν•„μš”ν•©λ‹ˆλ‹€. AuthService λ‹¨μ—μ„œ μ²˜λ¦¬ν•˜μ§€ μ•Šμ€ μ˜ˆμ™Έκ°€ μžˆμ„ 경우, 컨트둀러 λ‹¨μ—μ„œ λͺ…μ‹œμ μœΌλ‘œ μ²˜λ¦¬ν•˜λ„λ‘ κ²€ν† ν•΄μ£Όμ„Έμš”.

src/main/java/com/mycom/socket/auth/security/MemberDetails.java (1)

23-23: [KO] ROLE μ„€μ • κ²€ν† 
member.getRole()을 직접 μ‚¬μš©ν•˜κ³  μžˆμ§€λ§Œ, DBλ‚˜ Enum μ •μ˜ ꡬ쑰상 "ROLE_" 접두사λ₯Ό λΆ™μ—¬μ•Ό ν•  μˆ˜λ„ μžˆμŠ΅λ‹ˆλ‹€. Spring Security ν‘œμ€€ 관둀에 맞게 ROLE_USER, ROLE_ADMIN λ“± λ¬Έμžμ—΄λ‘œ μ„€μ •ν•˜λŠ”μ§€ ν™•μΈν•΄μ£Όμ„Έμš”.

src/main/java/com/mycom/socket/auth/jwt/JWTUtil.java (1)

49-56: [KO] 토큰 νŒŒμ‹± μ‹œ μ˜ˆμ™Έ 처리
getEmailμ—μ„œ parseSignedClaimsλ₯Ό μ‹€ν–‰ν•  λ•Œ 토큰 검증에 μ‹€νŒ¨ν•˜λ©΄ μ˜ˆμ™Έκ°€ λ°œμƒν•  수 μžˆμœΌλ―€λ‘œ, 좔가적인 μ˜ˆμ™Έ μ²˜λ¦¬κ°€ ν•„μš”ν•΄ λ³΄μž…λ‹ˆλ‹€.

src/test/java/com/mycom/socket/member/service/LoginIntegrationTest.java (1)

49-50: μš”μ²­ DTO ν…ŒμŠ€νŠΈμ— λŒ€ν•œ μΆ”κ°€ 검증 μ œμ•ˆ
LoginRequestDtoκ°€ 값이 λΉ„μ–΄ μžˆκ±°λ‚˜ 잘λͺ»λœ ν˜•μ‹μž„μ„ ν™•μΈν•˜λŠ” ν…ŒμŠ€νŠΈκ°€ μ—†μŠ΅λ‹ˆλ‹€. 둜그인 μ‹€νŒ¨ μ‹œλ‚˜λ¦¬μ˜€λ₯Ό μΆ”κ°€ μž‘μ„±ν•΄, DTO 검증 둜직이 μ œλŒ€λ‘œ μˆ˜ν–‰λ˜λŠ”μ§€ ν™•μΈν•˜λ©΄ μ’‹κ² μŠ΅λ‹ˆλ‹€.

src/test/java/com/mycom/socket/member/controller/RegisterControllerTest.java (1)

63-63: μœ νš¨μ„± 검증 ν…ŒμŠ€νŠΈ ν™•μž₯ μ œμ•ˆ
ν˜„μž¬λŠ” 잘λͺ»λœ 이메일, λ„ˆλ¬΄ 짧은 λ‹‰λ„€μž„, 짧은 λΉ„λ°€λ²ˆν˜Έ μ •λ„λ§Œ ν…ŒμŠ€νŠΈν•˜κ³  μžˆμŠ΅λ‹ˆλ‹€. μ‹€μ œ DTO 검증 둜직이 더 λ³΅μž‘ν•˜λ‹€λ©΄, 경계값 ν…ŒμŠ€νŠΈ(예: μ΅œλŒ€ 길이, 특수문자 포함 μ—¬λΆ€ λ“±)λ₯Ό μΆ”κ°€ν•΄μ„œ 보닀 νƒ„νƒ„ν•œ νšŒμ›κ°€μž… 검증 μ‹œλ‚˜λ¦¬μ˜€λ₯Ό ꡬ성해보면 μ’‹κ² μŠ΅λ‹ˆλ‹€.

src/main/java/com/mycom/socket/auth/service/AuthService.java (1)

82-89: λ‘œκ·Έμ•„μ›ƒ μΏ ν‚€ 제거 둜직 보완
logout λ©”μ„œλ“œλŠ” μΏ ν‚€λ₯Ό μ¦‰μ‹œ λ§Œλ£Œμ‹œν‚€κ³  μžˆμ§€λ§Œ, 둜컬 개발 ν™˜κ²½μ΄ μ•„λ‹Œ μ‹€μ œ 배포 ν™˜κ²½μ—μ„œλŠ” 도메인 섀정이 ν•„μš”ν•  μˆ˜λ„ μžˆμŠ΅λ‹ˆλ‹€. 도메인 λ―Έμ„€μ • μ‹œ μΏ ν‚€κ°€ μ œκ±°λ˜μ§€ μ•ŠλŠ” λ¬Έμ œκ°€ μžˆμ„ 수 μžˆμœΌλ―€λ‘œ, μ‹€μ œ 운영 ν™˜κ²½ λ’€μ—μ„œ 도메인을 μ„€μ •ν•˜λŠ”μ§€ μž¬ν™•μΈν•΄ λ³΄μ„Έμš”.

src/test/java/com/mycom/socket/member/service/LoginTest.java (1)

44-66: 둜그인 성곡 μ‹œ μΏ ν‚€ μœ νš¨μ„± ν…ŒμŠ€νŠΈ
μΏ ν‚€μ˜ maxAge, HttpOnly, Secure ν”Œλž˜κ·Έκ°€ λͺ¨λ‘ μ„€μ •λ˜λŠ” 것을 μ κ²€ν•˜κ³  μžˆμŠ΅λ‹ˆλ‹€. λ§Œμ•½ 도메인 섀정이 ν•„μš”ν•œ ν”„λ‘œμ νŠΈ ν™˜κ²½μ΄λΌλ©΄, μΏ ν‚€μ˜ 도메인도 검증 λ‘œμ§μ— 포함할 수 μžˆμŠ΅λ‹ˆλ‹€.

build.gradle (1)

62-64: JWT 라이브러리 μΆ”κ°€ 확인 ν•„μš”

이 μ˜μ‘΄μ„±λ“€μ€ JWT κΈ°λŠ₯ κ΅¬ν˜„μ— 핡심적인 역할을 ν•©λ‹ˆλ‹€. 버전 ν˜Έν™˜μ„±κ³Ό μ΅œμ‹  λ³΄μ•ˆ 곡지 사항을 μž¬ν™•μΈν•˜μ‹œκΈΈ ꢌμž₯λ“œλ¦½λ‹ˆλ‹€.

λ‹€μŒ 슀크립트λ₯Ό μ‹€ν–‰ν•˜μ—¬ μ΅œμ‹  버전 및 λ³΄μ•ˆ 이슈λ₯Ό μ κ²€ν•΄λ³΄μ„Έμš”:

Comment on lines 37 to 47
public boolean validateToken(String token) {
try {
Jwts.parser()
.verifyWith(secretKey)
.build()
.parseSignedClaims(token);
return true;
} catch (Exception e) {
return false;
}
}
Copy link

Choose a reason for hiding this comment

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

πŸ› οΈ Refactor suggestion

[KO] μ˜ˆμ™Έ 처리 λ‘œκΉ… 보강
validateToken λ©”μ„œλ“œμ—μ„œ Exception λ°œμƒ μ‹œ λ‹¨μˆœνžˆ return false둜 μ²˜λ¦¬ν•˜κ³  μžˆμŠ΅λ‹ˆλ‹€. λΆˆν•„μš”ν•œ 토큰 접근이 반볡될 경우λ₯Ό λŒ€λΉ„ν•΄ μ΅œμ†Œν•œμ˜ μ—λŸ¬ 둜그λ₯Ό λ‚¨κΈ°λŠ” 것이 μ’‹μŠ΅λ‹ˆλ‹€.

} catch (Exception e) {
+   log.warn("JWT 토큰 검증 쀑 μ˜ˆμ™Έ λ°œμƒ: {}", e.getMessage());
    return false;
}

Committable suggestion skipped: line range outside the PR's diff.

import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.status;

@WebMvcTest(RegisterController.class)
@WebMvcTest(AuthController.class)
Copy link

Choose a reason for hiding this comment

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

πŸ› οΈ Refactor suggestion

@WebMvcTest μ‚¬μš© μ‹œ Controller λ²”μœ„ 확인
@WebMvcTest(AuthController.class)둜 μ§€μ •λ˜μ–΄ μžˆμ§€λ§Œ, 클래슀λͺ…은 RegisterControllerTest둜 남아 μžˆμŠ΅λ‹ˆλ‹€. ν…ŒμŠ€νŠΈ λŒ€μƒ 클래슀 이름과 μ‹€μ œ ν…ŒμŠ€νŠΈν•˜λŠ” μ»¨νŠΈλ‘€λŸ¬κ°€ μΌμΉ˜ν•˜λ„λ‘ μˆ˜μ •ν•˜κ±°λ‚˜, 파일λͺ…을 AuthControllerTest λ“±μœΌλ‘œ λ³€κ²½ν•˜μ—¬ ν˜Όλ™μ„ μ€„μ΄λŠ” 편이 μ’‹κ² μŠ΅λ‹ˆλ‹€.

Comment on lines 50 to 62
MemberDetails memberDetails = (MemberDetails) authResult.getPrincipal();
Member member = memberDetails.getMember();

// JWT 토큰 생성
String token = jwtUtil.createToken(member.getEmail());

// HTTP Only 쿠킀에 JWT 토큰 μ €μž₯
Cookie cookie = new Cookie("Authorization", token);
cookie.setHttpOnly(true); // JavaScriptμ—μ„œ μ ‘κ·Ό λΆˆκ°€λŠ₯ν•˜κ²Œ μ„€μ •
cookie.setSecure(true); // HTTPSμ—μ„œλ§Œ μ „μ†‘λ˜λ„λ‘ μ„€μ •
cookie.setPath("/"); // λͺ¨λ“  κ²½λ‘œμ—μ„œ μΏ ν‚€ μ ‘κ·Ό κ°€λŠ₯
cookie.setMaxAge(1800); // μΏ ν‚€ λ§Œλ£Œμ‹œκ°„ 30λΆ„
response.addCookie(cookie);
Copy link

Choose a reason for hiding this comment

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

⚠️ Potential issue

JWT 토큰 μΏ ν‚€ μ„€μ • μ‹œ 취약점 확인
Authorization 쿠킀에 JWTκ°€ μ„€μ •λ˜μ–΄ μžˆλŠ”λ°, ν”„λ‘ νŠΈμ—”λ“œμ—μ„œ CSRF 곡격에 λŒ€ν•΄ λŒ€λΉ„ν•˜λŠ”μ§€ 확인해야 ν•©λ‹ˆλ‹€. HTTP-Only, Secure 섀정은 잘 λ˜μ–΄ μžˆμœΌλ‚˜, λ³΄μ•ˆ μš”κ΅¬μ‚¬ν•­μ— 따라 SameSite μ„€μ •(SameSite=Strict λ˜λŠ” Lax)을 κ³ λ €ν•˜λŠ” 것이 μ’‹μŠ΅λ‹ˆλ‹€.

Copy link

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

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

Actionable comments posted: 0

🧹 Nitpick comments (7)
src/main/java/com/mycom/socket/auth/jwt/JWTUtil.java (3)

18-22: [KO] λΉ„λ°€ ν‚€ λ³΄μ•ˆ κ°•ν™” μ œμ•ˆ
ν˜„μž¬ μ½”λ“œλŠ” μ• ν”Œλ¦¬μΌ€μ΄μ…˜ μ‹œμž‘ μ‹œμ μ— ν™˜κ²½ λ³€μˆ˜(@Value("${jwt.secret}"))λ‘œλΆ€ν„° λΉ„λ°€ ν‚€λ₯Ό λ°›μ•„ SecretKeyλ₯Ό μƒμ„±ν•˜κ³  μžˆμŠ΅λ‹ˆλ‹€. 이 λ•Œ, λΉ„λ°€ ν‚€ 관리가 μ–΄ν”Œλ¦¬μΌ€μ΄μ…˜ λ‚΄ ν™˜κ²½ λ³€μˆ˜ μ„€μ •μ—λ§Œ μ˜μ‘΄ν•  경우, 배포 ν™˜κ²½μ—μ„œ λˆ„μΆœ μœ„ν—˜μ΄ μžˆμ„ 수 μžˆμŠ΅λ‹ˆλ‹€. Secret Manager(예: AWS Secrets Manager, HashiCorp Vault λ“±)λ‚˜ μ»¨ν…Œμ΄λ„ˆ μ˜€μΌ€μŠ€νŠΈλ ˆμ΄μ…˜ νˆ΄μ—μ„œ μ œκ³΅ν•˜λŠ” λΉ„λ°€ ν‚€ 관리 κΈ°λŠ₯을 적극 κ³ λ €ν•΄ λ³΄μ•ˆμ„±μ„ ν•œμΈ΅ 높일 수 μžˆμŠ΅λ‹ˆλ‹€.


24-37: [KO] 토큰 생성 μ‹œ 좔가적인 ν΄λ ˆμž„ κ³ λ €
토큰에 λ‹΄κΈΈ 정보λ₯Ό email만 μ‚¬μš©ν•˜λŠ” 경우, μ°¨ν›„ μ‚¬μš©μž κ΄€λ ¨λœ λ‹€μ–‘ν•œ 정보λ₯Ό μΆ”κ°€ν•˜κΈ° μ–΄λ €μšΈ 수 μžˆμŠ΅λ‹ˆλ‹€. μ—­ν• (Role)μ΄λ‚˜ κΆŒν•œ(Permission)κ³Ό 같은 μΆ”κ°€ ν΄λ ˆμž„μ„ ν•¨κ»˜ μ €μž₯ν•˜λ©΄, 인가 λ‹¨κ³„μ—μ„œ ν† ν°λ§ŒμœΌλ‘œ νŠΉμ • λ¦¬μ†ŒμŠ€ μ ‘κ·Ό κΆŒν•œμ„ λΉ λ₯΄κ²Œ 검증할 수 μžˆμ–΄ ν™•μž₯성이 λ†’μ•„μ§‘λ‹ˆλ‹€.


52-59: [KO] νŒŒμ„œ ꡬ성 주의
ν† ν°μ—μ„œ 이메일을 μΆ”μΆœν•˜κΈ° μœ„ν•΄ parseSignedClaims(token).getPayload().getSubject()λ₯Ό μ‚¬μš©ν•˜κ³  μžˆμŠ΅λ‹ˆλ‹€. ν˜„μž¬ λ‘œμ§μ—λŠ” λ¬Έμ œκ°€ μ—†μ§€λ§Œ, ν™•μž₯ λ˜λŠ” λ‹€λ₯Έ ν΄λ ˆμž„ νŒŒμ‹± μ‹œμ μ„ κ³ λ €ν•  λ•Œ, νŒŒμ‹± 과정을 μœ μ—°ν•˜κ²Œ μž¬μ‚¬μš©ν•  수 μžˆλ„λ‘ λ³„λ„μ˜ 헬퍼 λ©”μ„œλ“œ(예: parseClaims(token))λ₯Ό 두면 가독성과 μœ μ§€λ³΄μˆ˜μ„±μ΄ ν–₯상될 수 μžˆμŠ΅λ‹ˆλ‹€.

src/test/java/com/mycom/socket/member/controller/AuthControllerTest.java (4)

23-25: ν…ŒμŠ€νŠΈ λŒ€μƒ 컨트둀러 변경에 λ”°λ₯Έ 영ν–₯
@WebMvcTest(AuthController.class)둜 섀정이 λ³€κ²½λ˜λ©΄μ„œ AuthControllerλ₯Ό ν…ŒμŠ€νŠΈ λŒ€μƒμœΌλ‘œ μ‚Όκ³  μžˆμŠ΅λ‹ˆλ‹€. SecurityConfigλ₯Ό μž„ν¬νŠΈν•˜μ—¬ μ‹œνλ¦¬ν‹° μ»¨ν…μŠ€νŠΈλ₯Ό μ˜¬λ°”λ₯΄κ²Œ κ΅¬μ„±ν•˜κ³  μžˆμŠ΅λ‹ˆλ‹€. 기타 λ³΄μ•ˆ μ„€μ •(예: JwtFilter λ“±)을 톡합 ν…ŒμŠ€νŠΈλ‘œλ„ 점검해 λ³΄λŠ” 것을 ꢌμž₯λ“œλ¦½λ‹ˆλ‹€.


34-34: MockBean μ£Όμž… λŒ€μ²΄ κ²€ν† 
@MockBean으둜 AuthServiceλ₯Ό μ£Όμž…λ°›μ•„ ν…ŒμŠ€νŠΈν•˜κ³  μžˆμŠ΅λ‹ˆλ‹€. μ£Όμš” 둜직이 λ³΅μž‘ν•΄μ§ˆ 경우, μ‹€μ œ Bean을 μ‚¬μš©ν•˜κ±°λ‚˜ λΆ„λ¦¬λœ 톡합 ν…ŒμŠ€νŠΈλ₯Ό κ³ λ €ν•΄λ³Ό 수 μžˆμŠ΅λ‹ˆλ‹€.


46-46: Service 계측 μŠ€ν… 확인
authService.register(any(RegisterRequestDto.class))의 μŠ€ν…μ„ 1L둜 λ°˜ν™˜ν•˜λ„λ‘ μ„€μ •ν•œ 뢀뢄은 정상 λ™μž‘μ„ ν™•μΈν•˜κΈ°μ— μΆ©λΆ„ν•©λ‹ˆλ‹€. 단, 좔가적인 μ˜ˆμ™Έ μΌ€μ΄μŠ€λ‚˜ 검증 λ‘œμ§μ— λŒ€ν•œ μ‹œλ‚˜λ¦¬μ˜€λ„ ν•¨κ»˜ ν…ŒμŠ€νŠΈν•œλ‹€λ©΄ ν’ˆμ§ˆ ν–₯상에 도움이 될 κ²ƒμž…λ‹ˆλ‹€.


63-63: μ˜ˆμ™Έ μΌ€μ΄μŠ€ ν…ŒμŠ€νŠΈ 보완 μ œμ•ˆ
이메일 ν˜•μ‹ 검증, 이름 길이 μ œν•œ, λΉ„λ°€λ²ˆν˜Έ 검증 등을 μ œλŒ€λ‘œ μ²˜λ¦¬ν•˜λŠ”μ§€ ν…ŒμŠ€νŠΈμ— ν¬ν•¨λ˜μ–΄ μžˆμŠ΅λ‹ˆλ‹€. λ‹€λ§Œ, μ„ΈλΆ€ 검증 둜직(예: 곡백 문자, 특수 문자 λ“±)을 μ’€ 더 λ‹€μ–‘ν•˜κ²Œ ν¬ν•¨ν•˜λ©΄ μ „λ°˜μ μΈ μž…λ ₯ μœ νš¨μ„± 검증이 ν•œμΈ΅ 강화될 κ²ƒμž…λ‹ˆλ‹€.

πŸ“œ Review details

Configuration used: .coderabbit.yaml
Review profile: CHILL
Plan: Pro

πŸ“₯ Commits

Reviewing files that changed from the base of the PR and between 4ce724a and 8f39fd6.

πŸ“’ Files selected for processing (3)
  • src/main/java/com/mycom/socket/auth/jwt/JWTUtil.java (1 hunks)
  • src/main/java/com/mycom/socket/auth/security/LoginFilter.java (1 hunks)
  • src/test/java/com/mycom/socket/member/controller/AuthControllerTest.java (4 hunks)
🚧 Files skipped from review as they are similar to previous changes (1)
  • src/main/java/com/mycom/socket/auth/security/LoginFilter.java
πŸ”‡ Additional comments (3)
src/main/java/com/mycom/socket/auth/jwt/JWTUtil.java (1)

39-49: [KO] μ˜ˆμ™Έ 처리 λ‘œκΉ… 보강
ν˜„μž¬ validateToken λ©”μ„œλ“œμ˜ μ˜ˆμ™Έ 처리 λΆ€λΆ„μ—μ„œλŠ” `` νƒœκ·Έκ°€ ν•„μš”ν•œ κ³Όκ±° μ½”λ©˜νŠΈμ™€ 거의 λ™μΌν•œ λ‘œκΉ… 방식을 μ‚¬μš©ν•˜κ³  μžˆμŠ΅λ‹ˆλ‹€. μ˜ˆμ™Έκ°€ λ°œμƒν–ˆμ„ λ•Œ μ΅œμ†Œν•œμ˜ 둜그λ₯Ό 남긴 것은 μΈμƒμ μž…λ‹ˆλ‹€. λ‹€λ§Œ, 반볡적이고 μ•…μ˜μ μΈ 토큰 μ‹œλ„κ°€ μžˆμ„ 경우λ₯Ό λŒ€λΉ„ν•˜μ—¬, μ˜ˆμ™Έ λ°œμƒ 타이밍과 횟수λ₯Ό κ΅¬λΆ„ν•˜μ—¬ κ²½κ³  둜그 레벨 μ΄μƒμ˜ 쑰치λ₯Ό μ·¨ν•˜λŠ” 방법도 κ²€ν† ν•΄ λ³Ό 수 μžˆμŠ΅λ‹ˆλ‹€.

src/test/java/com/mycom/socket/member/controller/AuthControllerTest.java (2)

5-7: μ£Όμš” μ˜μ‘΄μ„± μˆ˜μ • 확인
AuthController, RegisterRequestDto, AuthServiceλ₯Ό μƒˆλ‘œ μž„ν¬νŠΈν•˜μ—¬ 기쑴의 RegisterController κ΄€λ ¨ μ˜μ‘΄μ„±μ„ λŒ€μ²΄ν•˜κ³  μžˆμŠ΅λ‹ˆλ‹€. μ „λ°˜μ μΈ ꡬ쑰λ₯Ό 잘 λ°˜μ˜ν•˜μ˜€μœΌλ‚˜, κΈ°μ‘΄ μ»¨νŠΈλ‘€λŸ¬μ™€ DTO의 둜직 차이가 μ—†λŠ”μ§€ ν•œ 번 더 ν™•μΈν•΄λ³΄μ‹œλ©΄ μ’‹κ² μŠ΅λ‹ˆλ‹€.


40-40: ν…ŒμŠ€νŠΈ 데이터 검증
νšŒμ›κ°€μž… μš”μ²­ DTOλ₯Ό 생성할 λ•Œ "μ•ˆλ…•ν•˜μ„Έμš”"와 같은 문자 μž…λ ₯도 ν¬ν•¨ν•˜μ—¬ μœ λ‹ˆμ½”λ“œ μ²˜λ¦¬κ°€ μ •μƒμ μœΌλ‘œ μ΄λ€„μ§€λŠ”μ§€ 확인할 수 μžˆμŠ΅λ‹ˆλ‹€. λ‹€μ–‘ν•œ 언어와 특수 문자λ₯Ό ν…ŒμŠ€νŠΈ 데이터에 ν¬ν•¨ν•˜μ—¬ 포괄적인 검증을 ꢌμž₯ν•©λ‹ˆλ‹€.

@ohyuchan123 ohyuchan123 added βœ… Test test κ΄€λ ¨(storybook, jest...) πŸ”¨ Refactor μ½”λ“œ λ¦¬νŒ©ν† λ§ ✨ Feature κΈ°λŠ₯ 개발 labels Jan 6, 2025
@ohyuchan123 ohyuchan123 merged commit 32785e8 into develop Jan 6, 2025
1 of 2 checks passed
@ohyuchan123 ohyuchan123 changed the title Jwt Login πŸ”€ Jwt Login Jan 6, 2025
@coderabbitai coderabbitai bot mentioned this pull request Jan 8, 2025
@ohyuchan123 ohyuchan123 deleted the feature/jwt-login branch January 8, 2025 15:46
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

✨ Feature κΈ°λŠ₯ 개발 πŸ”¨ Refactor μ½”λ“œ λ¦¬νŒ©ν† λ§ βœ… Test test κ΄€λ ¨(storybook, jest...)

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants