๐ JWT(JSON Web Token)์ ์ธ ๋ถ๋ถ์ผ๋ก ๊ตฌ์ฑ๋๋ค.
HEADER.PAYLOAD.SIGNATURE
๐ JWT๋.
(์ )์ผ๋ก ๊ตฌ๋ถ๋ 3๊ฐ์ ํํธ๋ก ์ด๋ฃจ์ด์ ธ ์๋ค.
๊ฐ ๋ถ๋ถ์ Base64Url๋ก ์ธ์ฝ๋ฉ๋์ด ์ ๋ฌ๋๋ค.
๐ JWT์ ๋ฉํ๋ฐ์ดํฐ๋ฅผ ํฌํจํ๋ ๋ถ๋ถ์ด๋ค.
๋ณดํต ์ฌ์ฉํ ์๊ณ ๋ฆฌ์ฆ(HS256, RS256 ๋ฑ)๊ณผ ํ ํฐ ํ์ (JWT)์ ๋ด๋๋ค.
{ "alg": "HS256", // ์ฌ์ฉํ ํด์ฑ ์๊ณ ๋ฆฌ์ฆ (HMAC SHA256) "typ": "JWT" // ํ ํฐ ํ์ }
eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9
๐ ์ฌ์ฉ์์ ์ฃผ์ ์ ๋ณด(Claim)๊ฐ ํฌํจ๋๋ ๋ถ๋ถ์ด๋ค.
์ฆ, JWT์ ๋ณธ๋ฌธ ์ญํ ์ ํ๋ค.
๐ Claim(ํด๋ ์)์ JWT (JSON Web Token) ๋ด๋ถ์ ํฌํจ๋ ์ฌ์ฉ์ ์ ๋ณด(๋ฐ์ดํฐ) ํ์ด๋ก๋๋ฅผ ์๋ฏธํ๋ค.
์ฆ, JWT ์์ ๋ค์ด์๋ Key-Value ํํ์ ๋ฐ์ดํฐ๋ผ๊ณ ๋ณด๋ฉด ๋๋ค.
sub
(์ฃผ์ ), iss
(๋ฐ๊ธ์), exp
(๋ง๋ฃ ์๊ฐ)name
, email
, role
userId
, membershipType
{
"sub": "1234567890", // ์ฌ์ฉ์ ID (๋ฑ๋ก๋ ํด๋ ์)
"name": "John Doe", // ์ฌ์ฉ์ ์ด๋ฆ (๊ณต๊ฐ ํด๋ ์)
"admin": true, // ๊ด๋ฆฌ์ ์ฌ๋ถ (๋น๊ณต๊ฐ ํด๋ ์)
"exp": 1712345678 // ๋ง๋ฃ ์๊ฐ (UNIX timestamp, ๋ฑ๋ก๋ ํด๋ ์)
}
eyJzdWIiOiIxMjM0NTY3ODkwIiwibmFtZSI6IkpvaG4gRG9lIiwiYWRtaW4iOnRydWV9
Claims claims = jwtUtil.extractClaims(jwt);
@PostConstruct
public void init() {
byte[] bytes = Base64.getDecoder().decode(secretKey);
key = Keys.hmacShaKeyFor(bytes);
}
...
public Claims extractClaims(String token) {
return Jwts.parserBuilder()
.setSigningKey(key)
.build()
.parseClaimsJws(token)
.getBody();
}
๐ ํ ํฐ์ ๋ฌด๊ฒฐ์ฑ์ ๋ณด์ฅํ๊ธฐ ์ํ ๋์งํธ ์๋ช ์ด๋ค.
์ฆ, ํ ํฐ์ด ์๋ณ์กฐ๋์ง ์์์์ ๊ฒ์ฆํ๋ ์ญํ ์ ํ๋ค.
์๋ช ์ ๋ค์๊ณผ ๊ฐ์ด ์์ฑ๋๋ค.HMACSHA256( base64UrlEncode(header) + "." + base64UrlEncode(payload), secretKey )
eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9
.
eyJzdWIiOiIxMjM0NTY3ODkwIiwibmFtZSI6IkpvaG4gRG9lIiwiYWRtaW4iOnRydWV9
.
SflKxwRJSMeKKF2QT4fwpMeJf36POk6yJV_adQssw5c
eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJzdWIiOiIxMjM0NTY3ODkwIiwibmFtZSI6IkpvaG4gRG9lIiwiYWRtaW4iOnRydWUsImlhdCI6MTUxNjIzOTAyMn0. KMUFsIDTnFmyG3nMiGM6H9FNFUROf3wh7SmqJp-QV30
{
ย ย ย ย "sub": "1234567890",
ย ย ย ย "name": "John Doe",
ย ย ย ย "admin": true,
ย ย ย ย "iat": 1516239022
}
a-string-secret-at-least-256-bits-long