Notice
Recent Posts
Recent Comments
Today
Total
05-22 06:57
Link
관리 메뉴

Partially Committed

처음 κ΅¬ν˜„ν•΄λ³΄λŠ” access, refresh token λ°œκΈ‰ 둜직(Spring) λ³Έλ¬Έ

πŸ‘¨‍πŸ‘§‍πŸ‘¦ ν™œλ™/Couphone Server || KUIT ν”„λ‘œμ νŠΈ

처음 κ΅¬ν˜„ν•΄λ³΄λŠ” access, refresh token λ°œκΈ‰ 둜직(Spring)

WonderJay 2023. 8. 17. 22:20
728x90
λ°˜μ‘ν˜•
SMALL

https://github.com/versatile0010/Couphone-Server

|| Couphone, 쿠폰을 폰 μ•ˆμ—!

λ°±μ—”λ“œ κ°œλ°œμžκ°€ 되기둜 λ§ˆμŒλ¨Ήμ€ λ’€λ‘œ

 

처음으둜 μ°Έμ—¬ν•œ ν”„λ‘œμ νŠΈμ΄λ‹€.

 

λ‚˜λŠ” Spring κ²½ν—˜μ΄ μ•„μ£Ό μ μ—ˆκ³ 

 

λ³Έ ν”„λ‘œμ νŠΈ 기간이 1κ°œμ›” 반 μ •λ„λ‘œ μ§§μ•˜κΈ° λ•Œλ¬Έμ—

 

전체적인 완성도가 많이 λ–¨μ–΄μ§€λŠ” 것 κ°™μ•„ 많이 아쉬웠닀.

 

처음으둜 ν”„λ‘œμ νŠΈμ— μ°Έμ—¬ν•˜λ‹€ λ³΄λ‹ˆ λͺ¨λ“  λΆ€λΆ„μ—μ„œ μƒλ‹Ήνžˆ λ§‰λ§‰ν•œ 감정을 λŠλ‚„ 수 밖에 μ—†μ—ˆλŠ”λ°,

 

운이 μ’‹κ²Œλ„ 이것저것 직접 κ΅¬ν˜„ν•΄λ³Ό 수 있게 λ˜μ–΄μ„œ

 

κ°œμΈμ μœΌλ‘œλŠ” μ–»μ–΄κ°€λŠ” 점이 κ½€ λ§Žμ•˜λ‹€κ³  μƒκ°ν•œλ‹€.

 

μ—¬νŠΌ,

 

처음으둜 ν”„λ‘œμ νŠΈμ— μ°Έμ—¬ν•˜λ©° 느꼈던 막막함과 ν•΄κ²° 과정을 λ˜μƒˆκΈ°λ©°

 

" 처음으둜 κ΅¬ν˜„ν•΄λ³΄λŠ” " μ΄λΌλŠ” μ‹œλ¦¬μ¦ˆλ‘œ λΈ”λ‘œκ·Έμ— μ‚½μ§ˆν•œ 기둝을 남겨볼 생각이닀. 

 

 μ²« 번째 μ£Όμ œλŠ” μ²˜μŒμœΌλ‘œ κ΅¬ν˜„ν•΄λ³΄λŠ” access token, refresh token λ°œκΈ‰ λ‘œμ§μ΄λ‹€.

 

( λŒ€λž΅ 7 개 μ •λ„μ˜ 주제λ₯Ό κ³„νšν•˜κ³  μžˆλ‹€. )


 

1. μ„Έμ…˜ 기반 인증 λ°©μ‹μ΄λž€?

이전에 μŠ€ν„°λ””μ—μ„œ 인증/인가에 λŒ€ν•΄μ„œ κ³΅λΆ€ν•΄λ³΄μ•˜λ‹€.

 

인증 λ°©μ‹μ—λŠ” 크게 2 가지가 μ‘΄μž¬ν•œλ‹€.

 

λ°±μ—”λ“œμ—μ„œλŠ” μ„Έμ…˜ 기반의 인증 μ‹œμŠ€ν…œμ„ ꡬ좕할 μˆ˜λ„ 있고, 토큰 기반의 인증 μ‹œμŠ€ν…œμ„ ꡬ좕할 μˆ˜λ„ μžˆκ² λ‹€.

 

 

μ„Έμ…˜ 기반의 인증 방식은 μ‚¬μš©μžμ˜ 정보λ₯Ό μ„œλ²„μ˜ μ„Έμ…˜ μ €μž₯μ†Œμ— μ €μž₯ν•˜λŠ” 것이닀.

 

μ‚¬μš©μžκ°€ λ‘œκ·ΈμΈμ„ ν•˜λ©΄, κ΄€λ ¨ 인증 정보λ₯Ό μ„Έμ…˜ μ €μž₯μ†Œμ— μ €μž₯ν•˜κ³ 

 

μ‚¬μš©μžμ—κ²Œ Session ID λ₯Ό λ°œκΈ‰ν•œλ‹€. 

 

Session ID λŠ” λΈŒλΌμš°μ €μ— μΏ ν‚€ ν˜•νƒœλ‘œ μ €μž₯λ˜μ–΄ κ΄€λ¦¬λœλ‹€.

 

λΈŒλΌμš°μ €μ—μ„œλŠ” 인증 절차λ₯Ό 마친 맀 μš”μ²­λ§ˆλ‹€ HTTP cookie 헀더에 Session ID λ₯Ό ν¬ν•¨ν•˜μ—¬ μ„œλ²„μ— μ „μ†‘ν•œλ‹€.

 

μ„œλ²„λŠ” 전달받은 Session ID 에 ν•΄λ‹Ήν•˜λŠ” μ„Έμ…˜ 정보가 μ„Έμ…˜ μ €μž₯μ†Œμ— μ‘΄μž¬ν•œλ‹€λ©΄ ν•΄λ‹Ή μ‚¬μš©μžκ°€ μΈμ¦λ˜μ—ˆλ‹€κ³  νŒλ‹¨ν•œλ‹€.

 

μ΄λŸ¬ν•œ μ„Έμ…˜ 기반의 μ‹œμŠ€ν…œμ€ ν΄λΌμ΄μ–ΈνŠΈλ‘œλΆ€ν„°μ˜ 정보λ₯Ό κΈ°μ–΅ν•˜κΈ° μœ„ν•΄ μ„Έμ…˜μ„ 계속 μœ μ§€ν•΄μ•Ό ν•œλ‹€. (Stateful ν•˜λ‹€.)

 

μ΄λŸ¬ν•œ νŠΉμ§•μ€ μ„œλ²„λ₯Ό ν™•μž₯ν•˜λŠ” 데에 μžˆμ–΄ λΆˆλ¦¬ν•˜λ‹€.

 

λ˜ν•œ μ„œλ²„μ—μ„œ ν΄λΌμ΄μ–ΈνŠΈ 인증 정보λ₯Ό λͺ¨λ‘ μ €μž₯ν•˜κ³  있으렀면 ν΄λΌμ΄μ–ΈνŠΈ μˆ˜κ°€ λŠ˜μ–΄λ‚¨μ— 따라

 

정보λ₯Ό 어디에 μ–΄λ–»κ²Œ μ €μž₯ν•΄μ•Ό ν•  지에 λŒ€ν•œ 좔가적인 λ…Όμ˜κ°€ λ°œμƒν•˜κ²Œ 될 것이닀.

 

μΆ”κ°€μ μœΌλ‘œ 쀑간에 제 3 μžμ— μ˜ν•΄ session id κ°€ νƒˆμ·¨λ˜λ©΄, 

 

인증된 ν΄λΌμ΄μ–ΈνŠΈκ°€ μ•„λ‹˜μ—λ„ 그런 것 처럼 μ„œλ²„μ— μ ‘κ·Όν•  수 μžˆλ‹€λŠ” 것 λ˜ν•œ 문제점이 λœλ‹€.

 

μ΄λŸ¬ν•œ 단점을 κ·Ήλ³΅ν•˜κΈ° μœ„ν•΄ 토큰 기반의 인증 방식이 널리 μ‚¬μš©λ˜κ³  μžˆλ‹€.


2. ν† ν°κΈ°λ°˜ 인증

토큰 기반 인증 방식은 인증 정보λ₯Ό ν΄λΌμ΄μ–ΈνŠΈ ν† ν°μ˜ ν˜•νƒœλ‘œ 가지고 μžˆλŠ”λ‹€. 

 

 

λŒ€ν‘œμ μœΌλ‘œ μ‚¬μš©λ˜λŠ” 토큰은 JWT 인데,

 

μ‚¬μš©μžκ°€ 가지고 μžˆλŠ” 토큰을 HTTP 의 Authorization 헀더에 ν¬ν•¨μ‹œμΌœ 보내면

 

μ„œλ²„ μΈ‘μ—μ„œλŠ” ν•΄λ‹Ή 토큰이 μœ νš¨ν•œμ§€, 그리고 λ§Œλ£Œλ˜μ§€ μ•Šμ•˜λŠ”μ§€λ₯Ό ν™•μΈν•œ λ’€

 

토큰에 μ•”ν˜Έν™”λ˜μ–΄ 담겨져 μžˆλŠ” μ‚¬μš©μž 인증 정보λ₯Ό ν™•μΈν•˜μ—¬ 인증/인가λ₯Ό μˆ˜ν–‰ν•œλ‹€.

 

JWT 의 ν˜•νƒœλŠ” μ•„λž˜μ™€ κ°™μœΌλ©° ν•„μš”μ— 따라 μ»€μŠ€ν„°λ§ˆμ΄μ§• ν•  수 μžˆλ‹€.

 

https://jwt.io/

 

μ„Έμ…˜ 기반 λ°©μ‹μ—μ„œλŠ” session id 만 λ„˜κΈ°λ©΄ λ˜μ—ˆλ‹€λ©΄

 

토큰 기반 λ°©μ‹μ—μ„œλŠ” μœ„μ™€ 같이 κΈ΄ λ¬Έμžμ—΄μ„ λ„˜κ²¨μ•Ό ν•˜λ―€λ‘œ

 

더 λ§Žμ€ λ„€νŠΈμ›Œν¬ νŠΈλž˜ν”½μ„ μ‚¬μš©ν•œλ‹€.

 

토큰이 νƒˆμ·¨λ˜λ©΄ μ‚¬μš©μž 정보가 λ…ΈμΆœλ  우렀 λ˜ν•œ μ‘΄μž¬ν•œλ‹€. (μ΄λŠ” refresh token 을 λ„μž…ν•˜λ©° κ°œμ„  κ°€λŠ₯)

 

κ·ΈλŸΌμ—λ„ 토큰 기반 인증 방식이 ν˜„μž¬ λŒ€μ„Έ 인 μ΄μœ λŠ” λ°”λ‘œ ν™•μž₯μ„± λ•Œλ¬Έμ΄λΌκ³  ν•  수 μžˆλ‹€.

 

λŒ€μš©λŸ‰ 데이터λ₯Ό μ²˜λ¦¬ν•˜κΈ° μœ„ν•΄μ„œ 단일 μ„œλ²„μ˜ μ„±λŠ₯을 λ†’μ΄λŠ” λ°μ—λŠ” ν•œκ³„κ°€ 있기 λ•Œλ¬Έμ— μ„œλ²„μ˜ 개수λ₯Ό λŠ˜λ¦¬λŠ” λ°©ν–₯(Scale out)으둜 νŠœλ‹ν•˜λŠ”λ°,

 

토큰 기반 인증 방식은 μ„Έμ…˜ 기반의 인증 방식과 달리 인증 정보가 토큰에 μ €μž₯λ˜λ―€λ‘œ Scale out 에 μœ λ¦¬ν•˜λ‹€.

 

μ„Έμ…˜ 기반의 인증 방식은 μ„œλ²„ λ‚΄λΆ€μ˜ μ„Έμ…˜ μ €μž₯μ†Œμ— 인증 정보λ₯Ό μ €μž₯ν–ˆμ—ˆλŠ”λ°, Scale out 됨에 따라 μ„œλ²„κ°€ λŠ˜μ–΄λ‚˜λ©΄ μ„Έμ…˜ 정보λ₯Ό μ–΄λ–»κ²Œ 관리할 지에 λŒ€ν•œ 큰 λ²ˆκ±°λ‘œμ›€μ΄ μ‘΄μž¬ν•œλ‹€.

 


3. JWT

 

Header

-  JWT ν—€λ”μ—λŠ” ν† ν°μ˜ νƒ€μž…κ³Ό ν•΄μ‹± μ•Œκ³ λ¦¬μ¦˜ 방식이 μ €μž₯λœλ‹€.

 

PayLoad

-  PayLoad μ—μ„œλŠ” ν† ν°μ—μ„œ μ‚¬μš©ν•  정보 쑰각인 Claim 이 λ‹΄κ²¨μ Έμžˆλ‹€.

-  기본적으둜 sub(토큰 제λͺ©), exp(만료 μ‹œκ°„), iat(λ°œκΈ‰ μ‹œκ°„) 등이 담겨져 μžˆλ‹€.

-  ν•„μš”ν•˜λ‹€λ©΄ 좔가적인 정보λ₯Ό Claim 에 λ„£μ–΄λ‘˜ 수 μžˆμœΌλ‚˜,  ν† ν°μ˜ 길이가 길어짐에 따라 λ„€νŠΈμ›Œν¬ λΆ€ν•˜κ°€ μ¦κ°€ν•˜κΈ° λ§ˆλ ¨μ΄λ―€λ‘œ λΆˆν•„μš”ν•œ 정보λ₯Ό μ΅œλŒ€ν•œ μ§€μ–‘ν•˜λŠ” 것이 μ’‹λ‹€.

 

Signature 

-  Signature μ—λŠ” 토큰 인코딩/μœ νš¨μ„± 검증 μ‹œ μ‚¬μš©ν•˜λŠ” κ³ μœ ν•œ μ•”ν˜Έν™” μ½”λ“œκ°€ 담겨져 있으며,

-  μ†μƒλ˜λ©΄ μœ νš¨ν•˜μ§€ μ•Šμ€ ν† ν°μœΌλ‘œ νŒλ‹¨ν•œλ‹€.

 


4. Access Token, Refresh Token 

토큰 μ—­μ‹œ νƒˆμ·¨λ˜λ©΄ 인증/μΈκ°€λ˜μ§€ μ•Šμ€ 제 3μžλ‘œλΆ€ν„° μ„œλ²„ λ¦¬μ†ŒμŠ€κ°€ λ…ΈμΆœλ  수 μžˆλŠ” μœ„ν—˜μ„±μ΄ μ‘΄μž¬ν•œλ‹€.

 

이λ₯Ό μ΅œλŒ€ν•œ μ˜ˆλ°©ν•˜κΈ° μœ„ν•΄ ν† ν°μ˜ μ’…λ₯˜λ₯Ό 2 κ°€μ§€λ‘œ κ΅¬λΆ„ν•˜μ—¬ μƒμ„±ν•˜λŠ” 방법이 μžˆλ‹€.

 

Access token

- μœ νš¨κΈ°κ°„μ΄ 맀우 짧은 토큰(30λΆ„ μ΄ν•˜)으둜 둜그인 μ‹œ μ„œλ²„μ—μ„œ ν΄λΌμ΄μ–ΈνŠΈμœΌλ‘œ λ°˜ν™˜ν•œλ‹€.

 

Refresh token

- μœ νš¨κΈ°κ°„이 κΈ΄ 토큰(7일 정도)으둜 ν΄λΌμ΄μ–ΈνŠΈλ‘œ λ°˜ν™˜ν•˜μ§€ μ•Šκ³ , μ„œλ²„ λ‚΄λΆ€ DB μ—μ„œ κ΄€λ¦¬ν•œλ‹€.  

 

토큰 νƒˆμ·¨μ˜ μœ„ν—˜μ€ μ„œλ²„ - ν΄λΌμ΄μ–ΈνŠΈ κ°„ 톡신 κ³Όμ •μ—μ„œ μ‘΄μž¬ν•˜λŠ”λ°,

 

ν΄λΌμ΄μ–ΈνŠΈλ‘œ μ‘λ‹΅ν•˜λŠ” Access token 의 λ§Œλ£ŒκΈ°κ°„μ„ 맀우 짧게 μ„€μ •ν•¨μœΌλ‘œμ¨

 

νƒˆμ·¨λ˜λ”λΌλ„ μœ„ν—˜μ„±μ΄ 적도둝 ν•˜λŠ” 방법이닀.

 

λ³Έ ν”„λ‘œμ νŠΈμ—μ„œλ„ Access token , Refresh token λ°©μ‹μœΌλ‘œ 인증/인가 μ‹œμŠ€ν…œμ„ κ΅¬μΆ•ν•˜μ˜€λ‹€.

 

인증 κ΄€λ ¨ν•˜μ—¬ 전체적인 Flow λŠ” μ•„λž˜ μ•„ν‚€ν…μ³μ—μ„œ 처럼 μƒλ‹Ήνžˆ λ³΅μž‘ν•˜λ‹€.

 

사싀 이번 ν”„λ‘œμ νŠΈμ—μ„œλ„ 전체적인 λ‚΄μš© 전체λ₯Ό μ΄ν•΄ν•˜μ§€λŠ” λͺ»ν•˜κ³  κ΅¬ν˜„ν•˜κΈ΄ ν–ˆμ—ˆλ‹€..

 

μ•„λž˜ κ΅¬μ‘°λŠ” μ‘°λ§Œκ°„ μŠ€ν”„λ§ μ‹œνλ¦¬ν‹°λ₯Ό κ³΅λΆ€ν•˜λ©° μƒˆλ‘œμš΄ ν¬μŠ€νŒ…μ—μ„œ μ •λ¦¬ν•΄λ³΄κ³ μž ν•œλ‹€..!

 

λ³Έ ν”„λ‘œμ νŠΈμ—μ„œ κ΅¬ν˜„ν•œ κ°„λ‹¨ν•œ λ‚΄μš©λ§Œ μ†Œκ°œν•΄λ³΄λ„λ‘ ν•˜κ² λ‹€.

 

λ¨Όμ €, μ‚¬μš©μž Login μš”μ²­μ΄ λ“€μ–΄μ˜€λ©΄

μ‹ κ·œ νšŒμ›μ΄λ©΄ νšŒμ› κ°€μž… μ²˜λ¦¬ν•˜κ³ , κΈ°μ‘΄ νšŒμ›μ΄λ©΄ λ‘œκ·ΈμΈμ„ μˆ˜ν–‰ν•œλ‹€.

 

ν•΄λ‹Ή API λŠ” Token 검증을 ν•˜μ§€ μ•ŠλŠ”λ‹€. 

 

signin 이 호좜되면 UsernamePasswordAuthenticationToken 을 λ°œκΈ‰λ°›λŠ”λ‹€.

 

( 보톡 email κ³Ό password λ₯Ό μ‚¬μš©ν•˜μ§€λ§Œ, λ³Έ ν”„λ‘œμ νŠΈμ—μ„œ password λ₯Ό μ‚¬μš©μžλ‘œλΆ€ν„° μž…λ ₯받지 μ•ŠμŒμ— 따라 email κ³Ό name 을 μ‚¬μš©ν•˜κ²Œ λ˜μ—ˆλ‹€. )

 

그리고 AuthenticationToken 을 AuthenticationManager μ—κ²Œ μ „λ‹¬ν•˜μ—¬ 인증 정보λ₯Ό λ§Œλ“ λ‹€.

 

곧이어 SecurityContextHolder  에 μ‚¬μš©μžμ˜ 인증 정보λ₯Ό μ €μž₯ν•œλ‹€.

 

이후 JwtProvider 에 사전에 κ΅¬ν˜„ν•΄λ‘” generateAccessToken, generateRefreshToken λ©”μ„œλ“œμ— 인증 정보λ₯Ό λ„˜κ²¨μ£Όμ–΄

 

accessToken κ³Ό refreshToken 을 μƒμ„±ν•œλ‹€.

 

refresh token 은 DB 에 μ €μž₯ν•˜κ³ ,

 

accessToken 은 μ‚¬μš©μžμ—κ²Œ λ°˜ν™˜ν•œλ‹€.

 


μ€‘μš”ν•œ 것은 μ•„λž˜ μ½”λ“œμ΄λ‹€.

 

λ‘œκ·ΈμΈμ„ μ œμ™Έν•œ λͺ¨λ“  Http μš”μ²­μ€ TokenAuthenticationFilter 에 μ „λ‹¬λ˜λ„λ‘ κ΅¬ν˜„ν•˜μ˜€λ‹€.

 

ν•΄λ‹Ή ν•„ν„°μ—μ„œλŠ” access token / refresh token κ΄€λ ¨ λ‘œμ§μ„ μˆ˜ν–‰ν•˜κ³ 

 

ν•„μš” μ‹œ μž¬λ°œκΈ‰ 등을 μˆ˜ν–‰ν•œλ‹€.

 

@Slf4j
@RequiredArgsConstructor
public class TokenAuthenticationFilter extends OncePerRequestFilter {
    private final JwtTokenProvider jwtProvider;
    private final RefreshTokenService tokenService;
    private final static String HEADER_AUTHORIZATION = "Authorization";
    private final static String TOKEN_PREFIX = "Bearer ";

    @Override
    protected void doFilterInternal(HttpServletRequest request, HttpServletResponse response, FilterChain filterChain) throws ServletException, IOException {
        if (permitAllUrl.of(request.getRequestURI())) {
            filterChain.doFilter(request, response);
            return;
        }
        String accessToken = resolveToken(request, HEADER_AUTHORIZATION); // 1. μ‚¬μš©μžκ°€ 보낸 토큰을 확인

        if (StringUtils.hasText(accessToken) && jwtProvider.validateToke(accessToken) == JwtCode.ACCESS) {
            // Access token 이 μœ νš¨ν•˜λ©΄
            Authentication authentication = jwtProvider.getAuthentication(accessToken);
            SecurityContextHolder.getContext().setAuthentication(authentication); // security context 에 인증 정보 μ €μž₯
            log.info("Access Token 은 아직 μœ νš¨ν•©λ‹ˆλ‹€.");
        } else if (StringUtils.hasText(accessToken) && jwtProvider.validateToke(accessToken) == JwtCode.EXPIRED) {
            // 2-1. Access token 이 λ§Œλ£Œλ˜μ—ˆλ‹€λ©΄
            log.info("Authorization ν•„λ“œμ— 담겨진 Access Token 이 Expired λ˜μ—ˆμŠ΅λ‹ˆλ‹€!");
            String refreshToken = null;

            // 2-2. jwt token μœΌλ‘œλΆ€ν„° userId λ₯Ό μ°Ύκ³ , ν•΄λ‹Ή userId 에 λŒ€ν•œ refreshToken 을 탐색
            Long userId = jwtProvider.getUserIdFromExpiredToken(accessToken);
            log.warn(userId.toString());
            refreshToken = jwtProvider.getRefreshToken(userId);

            // refresh token 이 μ‘΄μž¬ν•˜κ³  μœ νš¨ν•˜λ‹€λ©΄
            if (StringUtils.hasText(refreshToken) && jwtProvider.validateToke(refreshToken) == JwtCode.ACCESS) {
                // access token μž¬λ°œκΈ‰
                log.info("ν•΄λ‹Ή νšŒμ› ID 에 λŒ€ν•œ Refresh token 이 μ‘΄μž¬ν•˜κ³  μœ νš¨ν•©λ‹ˆλ‹€.");
                log.info("Access token 을 μž¬λ°œκΈ‰ν•˜μ—¬ λ°˜ν™˜ν•©λ‹ˆλ‹€.");

                Authentication authentication = jwtProvider.getAuthentication(refreshToken);

                String newAccessToken = jwtProvider.generateAccessToken(authentication);
                SecurityContextHolder.getContext().setAuthentication(authentication);

                response.setHeader(HttpHeaders.AUTHORIZATION, newAccessToken);
            } else if (StringUtils.hasText(refreshToken) && jwtProvider.validateToke(refreshToken) == JwtCode.EXPIRED) {
                // refresh token 이 μ‘΄μž¬ν•˜μ§€λ§Œ λ§Œλ£Œλ˜μ—ˆλ‹€λ©΄
                log.warn("ν•΄λ‹Ή νšŒμ› ID 에 λŒ€ν•œ Refresh token 이 μ‘΄μž¬ν•˜μ§€λ§Œ, λ§Œλ£Œλ˜μ—ˆμŠ΅λ‹ˆλ‹€.");
                throw new JwtExpiredTokenException(EXPIRED_TOKEN);
            }
            if (refreshToken == null) {
                // refresh token 이 μ‘΄μž¬ν•˜μ§€ μ•ŠμœΌλ©΄
                log.warn("ν•΄λ‹Ή νšŒμ› ID 에 λŒ€ν•œ Refresh token 이 μ‘΄μž¬ν•˜μ§€ μ•ŠμŠ΅λ‹ˆλ‹€.");
                throw new JwtNoTokenException(TOKEN_NOT_FOUND);
            }
        }
        filterChain.doFilter(request, response);
    }

    public String resolveToken(HttpServletRequest request, String header) {
        String bearerToken = request.getHeader(header);
        if (StringUtils.hasText(bearerToken) && bearerToken.startsWith(TOKEN_PREFIX)) {
            return bearerToken.substring(TOKEN_PREFIX.length());
        }
        return null;
    }
}

https://github.com/KUIT-Couphone/Couphone-Server/pull/18

 

feat: JWT Authentication 둜직 κ°œμ„  및 μ˜ˆμ™Έμ²˜λ¦¬ 보완 by versatile0010 · Pull Request #18 · KUIT-Couphone/Couphone-Se

변경사항 JWT Authtentication Filter [ TokenAuthenticaionFilter ] token 검증이 ν•„μš”ν•˜μ§€ μ•ŠλŠ” path (e.g. /auth/login ) 에 λŒ€ν•΄μ„œλŠ” token μœ νš¨μ„±μ„ κ²€μ‚¬ν•˜μ§€ μ•Šκ³  λ„˜μ–΄κ°„λ‹€. access token 이 μœ νš¨ν•˜λ©΄ (μœ νš¨ν•˜μ§€ μ•ŠμœΌλ©΄ In

github.com


token κ²€μ¦μ΄ ν•„μš”ν•˜μ§€ μ•ŠλŠ” path (e.g. /auth/login ) μ— λŒ€ν•΄μ„œλŠ” token μœ νš¨μ„±μ„ κ²€μ‚¬ν•˜μ§€ μ•Šκ³  λ„˜μ–΄κ°„λ‹€.

 

access token μ΄ μœ νš¨ν•˜λ©΄ (μœ νš¨ν•˜μ§€ μ•ŠμœΌλ©΄ InvalidTokenException)

 

인증 μ •λ³΄λ₯Ό μ €μž₯ν•œλ‹€. (끝)

 

access token μ΄ μœ νš¨ν•˜μ§€λ§Œ λ§Œλ£Œλ˜μ—ˆλ‹€λ©΄

 

-  3.1 jwtμ—μ„œ userId λ₯Ό κΊΌλ‚Έλ‹€.
-  3.2 ν•΄λ‹Ή userId 에 λŒ€ν•œ refresh token 이 μœ νš¨ν•˜λ©΄ access token 을 μž¬λ°œκΈ‰ν•˜κ³  Authorization header 에 λ‹΄μ•„μ„œ λ°˜ν™˜ν•œλ‹€.
-  3.3 ν•΄λ‹Ή userId 에 λŒ€ν•œ refresh token 이 μ‘΄μž¬ν•˜μ§€ μ•ŠμœΌλ©΄ JwtNoTokenException
-  3.4 ν•΄λ‹Ή userId 에 λŒ€ν•œ refresh token 이 μ‘΄μž¬ν•˜μ§€λ§Œ λ§Œλ£Œλ˜μ—ˆλ‹€λ©΄ JwtExpiredTokenException

 

 


 

 

References

1. https://do5do.tistory.com/14

 

[Spring] Spring Security + JWT

Spring Security κΈ°λ°˜μ— JWT 인증 방식을 μ μš©ν•΄λ³΄μ•˜λ‹€. 인증 방식은 이렇닀. 1. ν΄λΌμ΄μ–ΈνŠΈκ°€ λ‘œκ·ΈμΈμ„ μš”μ²­ν•œλ‹€. 2. ID/PW 검증 ν›„ access token, rerfresh token을 λ°œκΈ‰ν•œλ‹€. 3. refresh token은 DB에 μ €μž₯ν•˜κ³ , access

do5do.tistory.com

2. https://goldenrabbit.co.kr/product/springboot3java/

 

[되기] μŠ€ν”„λ§ λΆ€νŠΈ 3 λ°±μ—”λ“œ 개발자 되기(μžλ°” 편) - κ³¨λ“ λž˜λΉ—

μžλ°” λ°±μ—”λ“œ κ°œλ°œμžκ°€ 되고 μ‹Άλ‹€λ©΄ μžλ°” κ·Έλ‹€μŒμ— κΌ­ λ³΄μ„Έμš”! μž…λ¬Έμžμ—κ²Œ λ°±μ—”λ“œ 개발의 ν•„μˆ˜ 지식을 ν•™μŠ΅ λ‘œλ“œλ§΅ μ€‘μ‹¬μœΌλ‘œ μ„€λͺ…ν•©λ‹ˆλ‹€. μŠ€ν”„λ§ λΆ€νŠΈ 3 κ°œλ°œμ— κΌ­ ν•„μš”ν•œ JPA ORM, OAuth2 인증, AWS λ°°

goldenrabbit.co.kr

3. https://product.kyobobook.co.kr/detail/S000001019679

 

μŠ€ν”„λ§ λΆ€νŠΈμ™€ AWS둜 혼자 κ΅¬ν˜„ν•˜λŠ” μ›Ή μ„œλΉ„μŠ€ | μ΄λ™μš± - ꡐ보문고

μŠ€ν”„λ§ λΆ€νŠΈμ™€ AWS둜 혼자 κ΅¬ν˜„ν•˜λŠ” μ›Ή μ„œλΉ„μŠ€ | κ°€μž₯ λΉ λ₯΄κ³  μ‰½κ²Œ μ›Ή μ„œλΉ„μŠ€μ˜ λͺ¨λ“  과정을 κ²½ν—˜ν•œλ‹€. κ²½ν—˜μ΄ μ‹€λ ₯이 λ˜λŠ” μˆœκ°„!이 책은 제λͺ© κ·ΈλŒ€λ‘œ μŠ€ν”„λ§ λΆ€νŠΈμ™€ AWS둜 μ›Ή μ„œλΉ„μŠ€λ₯Ό κ΅¬ν˜„ν•©λ‹ˆλ‹€

product.kyobobook.co.kr

4. https://mangkyu.tistory.com/57

 

[SpringBoot] SpringBoot둜 SpringSecurity 기반의 JWT 토큰 κ΅¬ν˜„ν•˜κΈ°

ν˜„λŒ€ μ›Ήμ„œλΉ„μŠ€μ—μ„œλŠ” 토큰을 μ‚¬μš©ν•˜μ—¬ μ‚¬μš©μžλ“€μ˜ 인증 μž‘μ—…μ„ μ²˜λ¦¬ν•˜λŠ” 것이 κ°€μž₯ 쒋은 방법이닀. μ΄λ²ˆμ—λŠ” 토큰 기반의 인증 μ‹œμŠ€ν…œμ—μ„œ 주둜 μ‚¬μš©ν•˜λŠ” JWT(Json Web Token)에 λŒ€ν•΄ SpringBoot와 Spring

mangkyu.tistory.com

 

728x90
λ°˜μ‘ν˜•
LIST
Comments