Hamutaro - Hamtaro 4

Backend/Spring

[Spring] JWT (JSON Web Token)

carsumin 2025. 2. 18. 22:34
JWT ๋ž€?
  • JSON Web Token, JSON ๊ฐ์ฒด๋ฅผ ์•ˆ์ „ํ•˜๊ฒŒ ์ „์†กํ•˜๊ธฐ ์œ„ํ•œ ํ† ํฐ ๊ธฐ๋ฐ˜ ์ธ์ฆ ๋ฐฉ์‹
  • ์ž๊ธฐ ํฌํ•จ (Self-contained) : ํ† ํฐ์•ˆ์— ์œ ์ € ์ •๋ณด๋‚˜ ๊ถŒํ•œ ๊ฐ™์€ ํ•„์š”ํ•œ ์ •๋ณด๋ฅผ ์ง์ ‘ ๋‹ด๊ณ  ์žˆ์–ด์„œ ๋ณ„๋„์˜ ์„ธ์…˜ ์ €์žฅ์†Œ๊ฐ€ ํ•„์š”์—†์Œ
  • ์„œ๋ช… (Signature) : ํ† ํฐ์€ ์„œ๋ช…๋˜์–ด ์žˆ์–ด์„œ ๋‚ด์šฉ์ด ์œ„์กฐ๋˜์ง€ ์•Š์•˜๋Š”์ง€ ๊ฒ€์ฆ์ด ๊ฐ€๋Šฅํ•จ
  • Stateless : ์„œ๋ฒ„๋Š” ํด๋ผ์ด์–ธํŠธ์˜ ์ƒํƒœ๋ฅผ ์œ ์ง€ํ•  ํ•„์š”์—†์ด ํ† ํฐ๋งŒ ํ™•์ธํ•˜๋ฉด ๋จ

 

JWT ๊ตฌ์กฐ
  • Header : ํ† ํฐ์˜ ํƒ€์ž…๊ณผ ํ•ด์‹ฑ ์•Œ๊ณ ๋ฆฌ์ฆ˜ (ex : HS256)
  • Payload : ์œ ์ € ์ •๋ณด ๋ฐ ํด๋ ˆ์ž„(claims)์ด ํฌํ•จ๋˜๋Š” ๋ฐ์ดํ„ฐ (ex : sub, name, exp ๋“ฑ)
  • Signature : ํ—ค๋”์™€ ํŽ˜์ด๋กœ๋“œ๋ฅผ ๋น„๋ฐ€ํ‚ค๋กœ ํ•ด์‹ฑํ•œ ์„œ๋ช…

 

JWT util class ์˜ˆ์ œ
import io.jsonwebtoken.*;
import io.jsonwebtoken.security.Keys;

import javax.crypto.SecretKey;
import java.util.Date;

public class JwtTokenUtil {
    // ๋น„๋ฐ€ํ‚ค (์‹ค์ œ๋กœ๋Š” ํ™˜๊ฒฝ๋ณ€์ˆ˜๋‚˜ config์— ๋ณด๊ด€)
    private final SecretKey secretKey = Keys.secretKeyFor(SignatureAlgorithm.HS256);

    // JWT ์œ ํšจ์‹œ๊ฐ„ (์˜ˆ: 1์‹œ๊ฐ„)
    private final long expirationMs = 1000 * 60 * 60;

    // JWT ์ƒ์„ฑ
    public String generateToken(String username) {
        return Jwts.builder()
                .setSubject(username) // ์‚ฌ์šฉ์ž ์‹๋ณ„์ž
                .setIssuedAt(new Date()) // ๋ฐœํ–‰ ์‹œ๊ฐ„
                .setExpiration(new Date(System.currentTimeMillis() + expirationMs)) // ๋งŒ๋ฃŒ ์‹œ๊ฐ„
                .signWith(secretKey) // ์„œ๋ช…
                .compact();
    }

    // JWT ๊ฒ€์ฆ ๋ฐ ํŒŒ์‹ฑ
    public Claims getClaims(String token) {
        return Jwts.parserBuilder()
                .setSigningKey(secretKey)
                .build()
                .parseClaimsJws(token)
                .getBody();
    }

    // ํ† ํฐ ๋งŒ๋ฃŒ ์—ฌ๋ถ€ ํ™•์ธ
    public boolean isTokenExpired(String token) {
        Date expiration = getClaims(token).getExpiration();
        return expiration.before(new Date());
    }

    // ์‚ฌ์šฉ์ž ์ด๋ฆ„ ์ถ”์ถœ
    public String getUsername(String token) {
        return getClaims(token).getSubject();
    }
}

 

 

JWT ์‚ฌ์šฉ ์˜ˆ์‹œ
  1. ๋กœ๊ทธ์ธ ์ธ์ฆ
    1. ์‚ฌ์šฉ์ž๊ฐ€ ๋กœ๊ทธ์ธ
    2. ์„œ๋ฒ„๊ฐ€ ์‚ฌ์šฉ์ž ์ •๋ณด๋ฅผ ๋ฐ”ํƒ•์œผ๋กœ JWT ๋ฐœ๊ธ‰
    3. ํด๋ผ์ด์–ธํŠธ๋Š” ์ดํ›„ ์š”์ฒญ๋งˆ๋‹ค JWT๋ฅผ ํ† ํฐ ํ˜•ํƒœ๋กœ ์ „์†ก
    4. ์„œ๋ฒ„๋Š” ํ† ํฐ์„ ๊ฒ€์ฆํ•˜์—ฌ ์ธ์ฆ ์ฒ˜๋ฆฌ
  2. SSO (Single Sign-On)
    • ์—ฌ๋Ÿฌ ์„œ๋น„์Šค๊ฐ€ ์žˆ๋Š” ์‹œ์Šคํ…œ์—์„œ ํ•œ ๋ฒˆ์˜ ๋กœ๊ทธ์ธ์œผ๋กœ ์—ฌ๋Ÿฌ ์„œ๋น„์Šค์— ์ ‘๊ทผํ•  ์ˆ˜ ์žˆ๋„๋ก JWT๋ฅผ ์‚ฌ์šฉ
    • ex : ํšŒ์‚ฌ ํฌํ„ธ์—์„œ ๋กœ๊ทธ์ธํ•˜๋ฉด ๋ฉ”์ผ, ์ธ์‚ฌ์‹œ์Šคํ…œ, ํšŒ๊ณ„์‹œ์Šคํ…œ ๋“ฑ ์ž๋™ ๋กœ๊ทธ์ธ
  3. ๋ชจ๋ฐ”์ผ ์•ฑ๊ณผ ์„œ๋ฒ„ ๊ฐ„ ํ†ต์‹ 
    • ๋ชจ๋ฐ”์ผ ์•ฑ์€ ์„ธ์…˜ ๋Œ€์‹  JWT๋ฅผ ์‚ฌ์šฉํ•˜์—ฌ ์ธ์ฆ ๋ฐ ๊ถŒํ•œ ๊ด€๋ฆฌ๋ฅผ ์ˆ˜ํ–‰
    • ์„œ๋ฒ„๊ฐ€ ์ƒํƒœ๋ฅผ ์ €์žฅํ•˜์ง€ ์•Š๊ธฐ ๋•Œ๋ฌธ์— ํ™•์žฅ์„ฑ์ด ์ข‹์Œ
  4. API ์ธ์ฆ ๋ฐ ๊ถŒํ•œ ์ฒ˜๋ฆฌ
    • ์‚ฌ์šฉ์ž ๊ถŒํ•œ (role: admin) ๋“ฑ์„ ํ† ํฐ์— ๋‹ด์•„ API ์ ‘๊ทผ์„ ์ œ์–ด

 

JWT ํ† ํฐ ์œ ํšจ์„ฑ ์ฒดํฌ
  • ์ƒ์„ฑํ•œ ํ† ํฐ์ด ์œ ํšจํ•œ์ง€ ์•„๋ž˜์˜ ์‚ฌ์ดํŠธ์—์„œ ๊ฒ€์‚ฌํ•  ์ˆ˜ ์žˆ์Œ
  • https://jwt.io/