JWT (JSON Web Token)์ด๋?
1. JWT ์ ์
JWT(JSON Web Token)๋ JSON ๊ฐ์ฒด๋ฅผ ์ฌ์ฉํ์ฌ ์ ๋ณด๋ฅผ ์์ ํ๊ฒ ์ ๋ฌํ๊ธฐ ์ํ ํ ํฐ ๊ธฐ๋ฐ ์ธ์ฆ ๋ฐฉ์์ด๋ค.
ํด๋ผ์ด์ธํธ์ ์๋ฒ ๊ฐ ์ธ์ฆ ๋ฐ ์ ๋ณด ๊ตํ์ ์ํด ์ฌ์ฉ๋๋ฉฐ, ๋์งํธ ์๋ช
์ด ํฌํจ๋์ด ์์ด ๋ฌด๊ฒฐ์ฑ์ด ๋ณด์ฅ๋๋ค.
๐ก JWT์ ํน์ง
โ๏ธ ๋ฌด์ํ(Stateless) ์ธ์ฆ
→ ์๋ฒ๊ฐ ์ธ์ ์ ์ ์ฅํ ํ์ ์์
โ๏ธ ํ ํฐ ๊ธฐ๋ฐ ์ธ์ฆ
→ ์ฌ์ฉ์ ๋ก๊ทธ์ธ ํ JWT๋ฅผ ์ด์ฉํ์ฌ ์ธ์ฆ
โ๏ธ ๋์งํธ ์๋ช ํฌํจ
→ ํ ํฐ ๋ณ์กฐ ๋ฐฉ์ง
โ๏ธ ๋ค์ํ ํ๊ฒฝ์์ ์ฌ์ฉ ๊ฐ๋ฅ
→ ์น, ๋ชจ๋ฐ์ผ, API ๋ฑ
2. JWT์ ๊ตฌ์กฐ
JWT๋ ์ (`.`)์ผ๋ก ๊ตฌ๋ถ๋ 3๊ฐ์ ๋ถ๋ถ์ผ๋ก ๊ตฌ์ฑ๋๋ค.
Header.Payload.Signature
- ์์ JWT:
eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJ1c2VyX2lkIjoxMjMsInJvbGUiOiJhZG1pbiJ9.jY3s5yOZ8YhQ12qG2WJlq8P4hHDcvb2XkJzzJgiOS78
1๏ธโฃ Header (ํค๋)
JWT์ ํ์ ๊ณผ ์๋ช ์๊ณ ๋ฆฌ์ฆ ์ ๋ณด๋ฅผ ํฌํจํ๋ค.
# json
{
"alg": "HS256", # ์๋ช
์๊ณ ๋ฆฌ์ฆ (์: HS256, RS256)
"typ": "JWT" # ํ ํฐ ์ ํ
}
2๏ธโฃ Payload (ํ์ด๋ก๋)
์ฌ์ฉ์ ์ ๋ณด(ํด๋ ์, Claims)๊ฐ ๋ค์ด๊ฐ๋ ๋ถ๋ถ
# json
{
"user_id": 123,
"role": "admin",
"exp": 1712345678 # ํ ํฐ ๋ง๋ฃ ์๊ฐ (Unix timestamp)
}
3๏ธโฃ Signature (์๋ช )
์๋ฒ์ ๋น๋ฐ ํค(secret key)๋ฅผ ์ด์ฉํ์ฌ ์๋ช ๋ ๊ฐ → ํ ํฐ ๋ณ์กฐ ๋ฐฉ์ง ์ญํ
HMACSHA256(
base64UrlEncode(header) + "." + base64UrlEncode(payload),
secret_key
)
3. JWT์ ๋์ ๋ฐฉ์
1๏ธโฃ ์ฌ์ฉ์๊ฐ ๋ก๊ทธ์ธ ์์ฒญ
- ํด๋ผ์ด์ธํธ๊ฐ `username`, `password`๋ฅผ ์ ๋ ฅํ์ฌ ์๋ฒ์ ๋ก๊ทธ์ธ ์์ฒญ
2๏ธโฃ ์๋ฒ๊ฐ JWT ์์ฑ ๋ฐ ๋ฐํ
- ์ฌ์ฉ์์ ์ธ์ฆ์ด ์๋ฃ๋๋ฉด, ์๋ฒ๋ `JWT`๋ฅผ ์์ฑํ๊ณ ํด๋ผ์ด์ธํธ์ ๋ฐํ
3๏ธโฃ ํด๋ผ์ด์ธํธ๋ JWT๋ฅผ ์ ์ฅ
- JWT๋ฅผ `LocalStorage`, `SessionStorage`, `์ฟ ํค` ๋ฑ์ ์ ์ฅ
4๏ธโฃ ์ธ์ฆ์ด ํ์ํ ์์ฒญ ์ JWT ํฌํจํ์ฌ ์ ์ก
- ํด๋ผ์ด์ธํธ๋ ์์ฒญ ํค๋์ JWT๋ฅผ ํฌํจํ์ฌ API ํธ์ถ
Authorization: Bearer <JWT_TOKEN>
5๏ธโฃ ์๋ฒ๋ JWT ๊ฒ์ฆ ํ ์์ฒญ ์ฒ๋ฆฌ
- ์๋ฒ๋ JWT์ ์๋ช ์ ํ์ธํ์ฌ ๋ณ์กฐ ์ฌ๋ถ ๊ฒ์ฆ
- ์ ํจํ ํ ํฐ์ด๋ฉด ์์ฒญ์ ์ ์ ์ฒ๋ฆฌ
4. JWT ํ์ฉ ์์ (Django + PyJWT)
Django์์ JWT๋ฅผ ์์ฑํ๊ณ ๊ฒ์ฆํ๋ ๊ธฐ๋ณธ์ ์ธ ์์
1๏ธโฃ JWT ์์ฑ (๋ก๊ทธ์ธ ์)
import jwt
import datetime
SECRET_KEY = "mysecretkey" # ๋ณด์ ํค
def create_jwt(user_id):
payload = {
"user_id": user_id,
"exp": datetime.datetime.utcnow() + datetime.timedelta(hours=1), # 1์๊ฐ ์ ํจ
"iat": datetime.datetime.utcnow() # ๋ฐ๊ธ ์๊ฐ
}
token = jwt.encode(payload, SECRET_KEY, algorithm="HS256")
return token
- `user_id`: ์ฌ์ฉ์ ID ํฌํจ
- `exp`: ํ ํฐ ๋ง๋ฃ ์๊ฐ ์ค์
- `iat`: ํ ํฐ ๋ฐ๊ธ ์๊ฐ
2๏ธโฃ JWT ๊ฒ์ฆ (์์ฒญ ์)
def verify_jwt(token):
try:
payload = jwt.decode(token, SECRET_KEY, algorithms=["HS256"])
return payload # ์ฌ์ฉ์ ์ ๋ณด ๋ฐํ
except jwt.ExpiredSignatureError:
return "ํ ํฐ์ด ๋ง๋ฃ๋์์ต๋๋ค."
except jwt.InvalidTokenError:
return "์ ํจํ์ง ์์ ํ ํฐ์
๋๋ค."
- `jwt.decode()`๋ฅผ ์ฌ์ฉํ์ฌ ํ ํฐ ํด๋
- ์๋ช ์ด ์ ํจํ๋ฉด ์ฌ์ฉ์ ์ ๋ณด ๋ฐํ
- ํ ํฐ์ด ๋ง๋ฃ๋์๊ฑฐ๋ ๋ณ์กฐ๋ ๊ฒฝ์ฐ ์์ธ ์ฒ๋ฆฌ
5. JWT์ ์ฅ์ ๊ณผ ๋จ์
์ฅ์ | ๋จ์ |
์๋ฒ๊ฐ ์ธ์ ์ ์ ์ฅํ ํ์ ์์ | ํ ํฐ ํฌ๊ธฐ๊ฐ ์ปค์ง ์ ์์ |
๋ถ์ฐ ํ๊ฒฝ์์ ์ธ์ฆ์ด ์ฉ์ด | ํ ํฐ์ด ํ์ทจ๋๋ฉด ๋ณด์ ๋ฌธ์ ๋ฐ์ ๊ฐ๋ฅ |
์๋ช ์ ์ด์ฉํ ๋ณ์กฐ ๋ฐฉ์ง | ํ ํฐ ๊ฐ์ ๋ก๊ทธ์์์ด ์ด๋ ค์ |
์ ํจ๊ธฐ๊ฐ ์ค์ ๊ฐ๋ฅ | ์์ฒด์ ์ผ๋ก ํ ํฐ ๋ฌดํจํ ๊ธฐ๋ฅ ์์ |
6. JWT vs ์ธ์ ๊ธฐ๋ฐ ์ธ์ฆ
๋น๊ต ํญ๋ชฉ | JWT (ํ ํฐ ๊ธฐ๋ฐ) | ์ธ์ ๊ธฐ๋ฐ ์ธ์ฆ |
์ํ ๊ด๋ฆฌ | ์๋ฒ๊ฐ ์ธ์ ์ ์ ์ฅํ์ง ์์ | ์๋ฒ๊ฐ ์ธ์ ์ ์ ์ฅ |
ํ์ฅ์ฑ | ์ํ ํ์ฅ์ด ์ฉ์ด | ํ์ฅ์ฑ์ด ๋ฎ์ |
์ธ์ฆ ๋ฐฉ์ | HTTP ํค๋์ ํ ํฐ ํฌํจ | ์ฟ ํค๋ฅผ ์ด์ฉ |
๋ณด์ | ํ ํฐ ํ์ทจ ์ ์ํ | ์ธ์ ๊ด๋ฆฌ ํ์ |
๋ฌดํจํ | ๋ณ๋ ๋ก์ง ํ์ (Blacklist) | ์ธ์ ์ญ์ ๊ฐ๋ฅ |
JWT ์ ๋ฆฌ:
1๏ธโฃ JWT๋ ํ ํฐ ๊ธฐ๋ฐ ์ธ์ฆ ๋ฐฉ์์ผ๋ก, ์ธ์ ์ ์ ์ฅํ์ง ์์ ์๋ฒ ํ์ฅ์ฑ์ด ๋ฐ์ด๋๋ค~
2๏ธโฃ 3๊ฐ์ ๊ตฌ์กฐ(Header, Payload, Signature)๋ก ๊ตฌ์ฑ๋๋ฉฐ, ์๋ช ์ ํตํด ๋ณ์กฐ๋ฅผ ๋ฐฉ์งํ๋ค~
3๏ธโฃ Django์์๋ PyJWT๋ฅผ ์ฌ์ฉํ์ฌ JWT๋ฅผ ์์ฑํ๊ณ ๊ฒ์ฆ ๊ฐ๋ฅํ๋ค~
4๏ธโฃ ํ ํฐ ํ์ทจ ๋ฐ ๋ณด์ ๋ฌธ์ ๋ฅผ ๊ณ ๋ คํ์ฌ ์ ์ ํ ๋ณด์ ์กฐ์น ํ์ํ๋ค~
'AI ๐ค > Django โ๏ธ' ์นดํ ๊ณ ๋ฆฌ์ ๋ค๋ฅธ ๊ธ
[250306] update()์ save()์ ์ฐจ์ด (0) | 2025.03.06 |
---|---|
[250305] Soft Delete๋? (0) | 2025.03.05 |
[250217] ์ธ์ฆ(Authentication)๊ณผ ๊ถํ(Authorization) (0) | 2025.02.17 |
[250213] API ๋ช ์ธ์ ์์ฑ๋ฒ๊ณผ ํ์์ฑ์ ๋ํ์ฌ (5) | 2025.02.13 |
[250210] Django Admin ์ ๋ฆฌ~ (1) | 2025.02.10 |