JWT ์๋ช ์ ์ํ HMAC ํค๋ฅผ ์์ ํ๊ฒ ์์ฑํ๋ ๋ฉ์๋
์ด ๋ฉ์๋๋ JJWT ๋ผ์ด๋ธ๋ฌ๋ฆฌ์์ ์ ๊ณต๋๋ฉฐ, JWT๋ฅผ ์์ฑํ ๋ ์๋ช (Signature) ๋ถ๋ถ์ ํ์ํ ํค๋ฅผ ๋ง๋๋๋ฐ ์ฌ์ฉ๋๋ค.
String secret = ~~;
SecretKey key = Keys.hmacShakeyFor(secret.getBytes));
secret.getBytes() : ๋ฌธ์์ด์ ๋ฐ์ดํธ ๋ฐฐ์ด๋ก ๋ณํhmacShaKeyFor(...) : ๋ฐ์ดํธ ๋ฐฐ์ด์ ๊ธธ์ด์ ๋ฐ๋ผ HMAC ์๊ณ ๋ฆฌ์ฆ ํค ์์ฑ์ด ๋ฉ์๋๋ ๋ด๋ถ์ ์ผ๋ก HMAC-SHA ์๊ณ ๋ฆฌ์ฆ (HS256, HS384, HS512)์ ์ฌ์ฉํ ์ ์๋ ํค๋ฅผ ์์ฑํ๋ค.
HMAC (Hash-based Message Authentication Code)
HMAC์ ํด์ ํจ์๋ฅผ ๊ธฐ๋ฐ์ผ๋ก ๋ฉ์์ง์ ๋ฌด๊ฒฐ์ฑ๊ณผ ์ธ์ฆ์ ๋ณด์ฅํ๊ธฐ ์ํ ๋ฐฉ์์ด๋ค.
์
๋ ฅ๊ฐ : ๋ฉ์์ง + ๋น๋ฐ ํค
๊ฒฐ๊ณผ๊ฐ : ์๋ช
(Signature)
HMAC(secret, message) : ๋ฉ์์ง๊ฐ ์์กฐ๋์ง ์์๋์ง, ์ธ์ฆ๋ ํค๋ก ์์ฑ๋ ๊ฒ์ธ์ง ํ์ธ ๊ฐ๋ฅํ๊ฒ ํด์ฃผ๋ ๋ฐฉ๋ฒ
SHA (Secure Hash Algorithm)
ํด์ ํจ์๋ก ์ฃผ์ด์ง ๋ฐ์ดํฐ๋ฅผ ๊ณ ์ ๋ ๊ธธ์ด์ ๋ฌด์์ ๊ฐ์ ๊ฐ์ผ๋ก ๋ฐ๊พธ๋ ํจ์๋ค.
๋ค์ํ ๋นํธ ์๋ฅผ ์ง์ํ๋ค.
SHA-256 - 256๋นํธ, SHA-384-384๋นํธ, SHA-512-512๋นํธ
HMAC + SHA = HMAC-SHA
๋์ ์กฐํฉํด์ ๋ง๋ ์๊ณ ๋ฆฌ์ฆ
| ์๊ณ ๋ฆฌ์ฆ | ์๋ฏธ | ํน์ง |
|---|---|---|
| HS256 | HMAC with SHA-256 | ๊ฐ์ฅ ์ผ๋ฐ์ ์ผ๋ก ์ฌ์ฉ |
| HS384 | HMAC with SHA-384 | ๋ ๊ฐํ ๋ณด์ |
| HS512 | HMAC with SHA-512 | ๋งค์ฐ ๊ฐํ ๋ณด์, ํค๋ ๋ ๊น |
JWT 3๋ถ๋ถ์์ Signature ๋ถ๋ถ์์ ์ฌ์ฉ
Header:
{
"alg": "HS256",
"typ": "JWT"
}
Payload:
{
"sub": "user123",
"role": "USER"
}
// HMAC-SHA๋ก ๋ง๋ ์๋ช
. ์ด๊ฑธ๋ก ์์กฐ ์ฌ๋ถ ํ๋จ
Signature = HMAC_SHA256(secret, base64url(Header) + "." + base64url(Payload))
javax.crypto.spec.SecretKeySpec
๋ฐ์ดํธ ๋ฐฐ์ด๋ก๋ถํฐ ๋์นญํค ๊ฐ์ฒด๋ฅผ ์์ฑํ ์ ์๊ฒ ํด์ฃผ๋ ํด๋์ค
SecretKey ์ธํฐํ์ด์ค๋ฅผ ๊ตฌํํ ํด๋์ค๋ก ์ํธํ ์๊ณ ๋ฆฌ์ฆ์ ์ฌ์ฉํ ์ค์ ํค ๊ฐ์ฒด๋ฅผ ์์ฑํ๋ ๋ฐ ์ฌ์ฉ๋๋ค.
๋ฐ์ดํธ ๋ฐฐ์ด(byte[]) + ์๊ณ ๋ฆฌ์ฆ ์ด๋ฆ(String)์ ๋๊ฒจ์ฃผ๋ฉด, SecretKey ๊ฐ์ฒด๊ฐ ์์ฑ๋๋ค.
public class SecretKeySpec implements SecretKey
ํน์ ์๊ณ ๋ฆฌ์ฆ์ ์ฌ์ฉํ ํค๋ฅผ ์ง์ ๋ง๋ค๊ณ ์ถ์ ๊ฒฝ์ฐ ์ฌ์ฉํ๋ค.
์ : AES, HMAC ๋ฑ์์ ์๋ช
๋๋ ์ํธํ์ ์ฌ์ฉํ ํค๋ฅผ ์ง์ ์ค์ ํด์ผ ํ ๋
import javax.crypto.spec.SecretKeySpec;
import javax.crypto.SecretKey;
String secret = "this-is-a-very-secret-key-32bytes!";
// ํด๋น ํค๋ฅผ JJWT, Mac, Cipher ๋ฑ์ ์ ๋ฌ
byte[] keyBytes = secret.getBytes();
// HmacSHA256๋ ์ฌ์ฉํ ์๊ณ ๋ฆฌ์ฆ ์ด๋ฆ
SecretKey key = new SecretKeySpec(keyBytes, "HmacSHA256");
| ํญ๋ชฉ | SecretKeySpec | Keys.hmacShaKeyFor() |
|---|---|---|
| ์ ๊ณต ์์น | Java ๊ธฐ๋ณธ API | JJWT ๋ผ์ด๋ธ๋ฌ๋ฆฌ |
| ์ฉ๋ | ๋ฐ์ดํธ ๋ฐฐ์ด๋ก ๋์นญํค ๋ง๋ค๊ธฐ | JWT ์๋ช ์ ์ํ ์์ ํ HMAC ํค ์์ฑ |
| ํค ๊ธธ์ด ๊ฒ์ฌ | โ (์ง์ ๊ฒ์ฆํด์ผ ํจ) | โ (256๋นํธ ์ด์ ์๋๋ฉด ์์ธ ๋ฐ์) |
| ํธ์์ฑ | ๋ฎ์ | ๋์ |
| ๊ถ์ฅ ์ฌ๋ถ | ๊ธฐ๋ณธ ์๊ณ ๋ฆฌ์ฆ ์ฌ์ฉ ์ OK | JWT์ฉ ํค ์์ฑ ์ ๋ ๊ถ์ฅ๋จ |
hmacShaKeyFor()๋ ๋ด๋ถ์ ์ผ๋ก SecretKeySpec์ ์ฌ์ฉํ์ง๋ง, ์๋์ผ๋ก ์์ ์ฑ๊ณผ ๊ธธ์ด ๊ฒ์ฌ๋ฅผ ํด์ฃผ๊ธฐ ๋๋ฌธ์ ๋ ์์ ํ๊ณ ํธ๋ฆฌํ๋ค.JWT๋ฅผ ์์ฑํ ๋ ์ฌ์ฉํ๋ ๋ฉ์๋๋ก, JWT์ payload ์์ญ์ ์ํ๋ ์ฌ์ฉ์ ์ ์ ๋ฐ์ดํฐ๋ฅผ ์ถ๊ฐํ ๋ ์ฌ์ฉ๋๋ค.
io.jsonwebtoken.JwtBuilder ์ธํฐํ์ด์ค์ ์ ์๋์ด ์์ผ๋ฉฐ, Jwts.builder()๋ฅผ ํตํด ๋ฐํ๋ JwtBuilder ๊ฐ์ฒด์์ ์ฌ์ฉ
Jwts.builder()
.subject(username) // ํ์ค ํด๋ ์: subject
.claim("email", email) // ์ปค์คํ
ํด๋ ์: ์ด๋ฉ์ผ
.claim("role", role) // ์ปค์คํ
ํด๋ ์: ์ญํ
.issuedAt(now)
.expiration(expiryDate)
.signWith(secretKey)
.compact();
JWT์ payload ์์ญ์ ์ฌ๋ฌ ๊ฐ์ ํด๋ ์์ผ๋ก ๊ตฌ์ฑ๋์ด์๋ค. ํด๋ ์์ ํ ํฐ์ ๋ด๊ธด ์ ๋ณด ์กฐ๊ฐ์ด๋ค.
Header . Payload . Signature
์ด ์ค Payload ๋ถ๋ถ์ ๋ด๊ธด ์ ๋ณด๊ฐ ๋ฐ๋ก Claims (์: ์ฌ์ฉ์ ์ด๋ฆ, ์ด๋ฉ์ผ, ๊ถํ(Role) ๋ฑ)
key-value ๋ฐ์ดํฐ ์งํฉ์ด๋ค.
public Claims extractClaims(String token) {
return Jwts.parser()
.verifyWith(secretKey) // ๋ด๋ถ์ ์ผ๋ก ์๋ช
๋ ๊ฒ์ฆ
.build()
.parseSignedClaims(token)
.getPayload();
}
{
"sub": "user1",
"email": "user1@example.com",
"role": "USER",
"exp": 1722315123
}
| ํญ๋ชฉ | ์ค๋ช |
|---|---|
| ์ ์ฒด | Claims ๊ฐ์ฒด |
"sub": "user1" | ํ๋์ Claim |
"email": "user1@example.com" | ํ๋์ Claim |
"role": "USER" | ํ๋์ Claim |
| ๊ตฌ๋ถ | ์ค๋ช |
|---|---|
Claims | ์ฌ๋ฌ ๊ฐ์ Claim์ ๋ด์ Map ํํ ๊ฐ์ฒด (Map<String, Object>) |
Claim | ๊ทธ ์์ ๋ค์ด์๋ ๋จ์ผ ์ ๋ณด (์: username, role, exp ๋ฑ) |
public String getUsername(String token) {
return extractClaims(token).getSubject();
}
// ์ด๋ฉ์ผ ์ถ์ถ
public String getEmail(String token) {
return extractClaims(token).get("email", String.class);
}
// ์ญํ (role) ์ถ์ถ
public String getRole(String token) {
return extractClaims(token).get("role", String.class);
}
createToken() ํธ์ถํ์ฌ JWT ์์ฑvalidateToken()์ ํตํด ์ ํจ์ฑ ๊ฒ์ฌusername, email, role)๋ ์ถ์ถ ๋ฉ์๋๋ก ๊บผ๋ํ๋ก์ ํธ์์ JwtUtil์ ์ฌ์ฉํ๋ ๊ณผ์ ์์ ๊ถ๊ธํ๋ ๋ถ๋ถ๋ค๊ณผ ๊ฐ๋ ์ ์ ํํ ์ดํดํ๊ธฐ ์ํด ๊ด๋ จ ๋ด์ฉ์ ํ์ตํ๋ค. ๊ณต๋ถ๋ฅผ ํ๋ค ๋ณด๋ ๊ฐ๋ ์ด ํ์ฅ๋์ด SecretKeySpec๊น์ง ๊น์ด ์๊ฒ ์ดํด๋ณด๊ฒ ๋์๋ค