-
Notifications
You must be signed in to change notification settings - Fork 0
π Jwt Login #24
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
π Jwt Login #24
Conversation
Walkthroughμ΄ ν 리νμ€νΈλ μ ν리μΌμ΄μ μ μΈμ¦ λ° λ³΄μ λ©μ»€λμ¦μ μ λ©΄μ μΌλ‘ μ¬μ€κ³ν©λλ€. JWT(JSON Web Token) κΈ°λ° μΈμ¦ μμ€ν μ λμ νμ¬ μ¬μ©μ λ‘κ·ΈμΈ, λ‘κ·Έμμ, λ±λ‘ νλ‘μΈμ€λ₯Ό κ°μ ν©λλ€. μλ‘μ΄ λ³΄μ ꡬμ±, μΈμ¦ νν°, ν ν° μ νΈλ¦¬ν° ν΄λμ€λ₯Ό μΆκ°νκ³ κΈ°μ‘΄ λ±λ‘ κ΄λ ¨ μ»΄ν¬λνΈλ₯Ό 리ν©ν λ§νμ¬ λμ± μμ νκ³ ν¨μ¨μ μΈ μΈμ¦ λ©μ»€λμ¦μ ꡬνν©λλ€. Changes
Sequence DiagramsequenceDiagram
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 μΏ ν€ λ° μ¬μ©μ μ 보
Possibly related PRs
Suggested labels
Poem
πͺ§ TipsChatThere are 3 ways to chat with CodeRabbit:
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)
Other keywords and placeholders
Documentation and Community
|
There was a problem hiding this 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
π 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μ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 κΈ°λ₯ ꡬνμ ν΅μ¬μ μΈ μν μ ν©λλ€. λ²μ νΈνμ±κ³Ό μ΅μ 보μ κ³΅μ§ μ¬νμ μ¬νμΈνμκΈΈ κΆμ₯λ립λλ€.
λ€μ μ€ν¬λ¦½νΈλ₯Ό μ€ννμ¬ μ΅μ λ²μ λ° λ³΄μ μ΄μλ₯Ό μ κ²ν΄λ³΄μΈμ:
| public boolean validateToken(String token) { | ||
| try { | ||
| Jwts.parser() | ||
| .verifyWith(secretKey) | ||
| .build() | ||
| .parseSignedClaims(token); | ||
| return true; | ||
| } catch (Exception e) { | ||
| return false; | ||
| } | ||
| } |
There was a problem hiding this comment.
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) |
There was a problem hiding this comment.
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 λ±μΌλ‘ λ³κ²½νμ¬ νΌλμ μ€μ΄λ νΈμ΄ μ’κ² μ΅λλ€.
| 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); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
JWT ν ν° μΏ ν€ μ€μ μ μ·¨μ½μ νμΈ
Authorization μΏ ν€μ JWTκ° μ€μ λμ΄ μλλ°, νλ‘ νΈμλμμ CSRF 곡격μ λν΄ λλΉνλμ§ νμΈν΄μΌ ν©λλ€. HTTP-Only, Secure μ€μ μ μ λμ΄ μμΌλ, 보μ μꡬμ¬νμ λ°λΌ SameSite μ€μ (SameSite=Strict λλ Lax)μ κ³ λ €νλ κ²μ΄ μ’μ΅λλ€.
There was a problem hiding this 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] ν ν° μμ± μ μΆκ°μ μΈ ν΄λ μ κ³ λ €
ν ν°μ λ΄κΈΈ μ 보λ₯Ό
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
π 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λ₯Ό μμ±ν λ"μλ νμΈμ"μ κ°μ λ¬Έμ μ λ ₯λ ν¬ν¨νμ¬ μ λμ½λ μ²λ¦¬κ° μ μμ μΌλ‘ μ΄λ€μ§λμ§ νμΈν μ μμ΅λλ€. λ€μν μΈμ΄μ νΉμ λ¬Έμλ₯Ό ν μ€νΈ λ°μ΄ν°μ ν¬ν¨νμ¬ ν¬κ΄μ μΈ κ²μ¦μ κΆμ₯ν©λλ€.
π κ΄λ ¨ μ΄μ
#22 Jwt λ‘κ·ΈμΈ κ΅¬ν
β¨ κ³Όμ λ΄μ©
κΈ°μ‘΄ μΈμ κΈ°λ° μΈμ¦μμ JWT κΈ°λ° μΈμ¦μΌλ‘ μ ννμ΅λλ€. 보μ κ°νλ₯Ό μν΄ ν ν°μ
HttpOnly μΏ ν€μ μ μ₯νλ λ°©μμ μ±ννμΌλ©°, λ€μκ³Ό κ°μ 보μ μ‘°μΉλ₯Ό μ μ©νμ΅λλ€:
πΈ μ€ν¬λ¦°μ·(μ ν)
π λ νΌλ°μ€ (λλ μλ‘ μκ² λ λ΄μ©) νΉμ κΆκΈν μ¬νλ€
Summary by CodeRabbit
λ¦΄λ¦¬μ¦ λ ΈνΈ
μλ‘μ΄ κΈ°λ₯
κ°μ μ¬ν
κΈ°μ μ λ³κ²½