آشنایی با JWT و ساخت توکن دسترسی در فلسک
آشنایی با JWT و ساخت توکن دسترسی در فلسک
JWT چیست؟
JSON Web Token یا به اختصار JWT، یک استاندارد باز (RFC 7519) برای ایجاد توکنهای امن است که اطلاعات را به صورت JSON منتقل میکنند. برخلاف نشستهای (Session) سنتی که اطلاعات کاربر را روی سرور ذخیره میکنند، JWTها بدون وضعیت (Stateless) هستند. این یعنی سرور نیازی نیست حافظهای برای نگهداری وضعیت کاربر داشته باشد؛ تمام اطلاعات مورد نیاز در داخل خود توکن قرار دارد و توسط امضای دیجیتال (Digital Signature) محافظت میشود.
ساختار یک توکن JWT
یک توکن JWT از سه بخش جداگانه تشکیل شده که با نقطه (.) از هم جدا میشوند:
- Header (سرآیند): شامل نوع توکن (JWT) و الگوریتم امضایی است (مثل HMAC SHA256).
- Payload (بارگذاری): شامل ادعاها (Claims) یا همان دادههایی است که میخواهیم منتقل کنیم (مثل شناسه کاربر، نام کاربری و زمان انقضا).
- Signature (امضا): بخشی است که برای تایید صحت توکن استفاده میشود تا مطمئن شویم توکن توسط شخص دیگری تغییر نکرده است.
چگونه JWT ساخته میشود؟ (روند ساده)
برای ساخت یک JWT، مراحل زیر به صورت دستی و منطقی طی میشود. بیایید فرض کنیم میخواهیم یک توکن برای کاربری با شناسه ۱۲۳۴ بسازیم.
۱. ساخت Header
ابتدا یک شیء JSON میسازیم که الگوریتم و نوع را مشخص میکند:
{
"alg": "HS256",
"typ": "JWT"
}
سپس این شیء را به رشته متنی تبدیل کرده و با استفاده از فرمت Base64Url کدگذاری میکنیم. فرض کنید خروجی این بخش به صورت زیر شود:
eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9
۲. ساخت Payload
حالا دادههایی که میخواهیم در توکن ذخیره کنیم (Claims) را در یک شیء JSON قرار میدهیم. معمولاً زمان انقضا (exp) را نیز اضافه میکنیم:
{
"sub": "۱۲۳۴",
"name": "علی محمدی",
"iat": ۱۵۱۶۲۳۹۰۲۲
}
این بخش را نیز به رشته تبدیل کرده و با Base64Url کدگذاری میکنیم. خروجی فرضی:
eyJzdWIiOiIxMjM0NTY3ODkwIiwibmFtZSI6IkpvaG4gRG9lIiwiaWF0IjoxNTE2MjM5MDIyfQ
۳. ساخت Signature (امضا)
این بخش مهمترین قسمت برای امنیت است. ما یک “کلید مخفی” (Secret Key) داریم که فقط سرور آن را میداند. امضا با استفاده از الگوریتم مشخص شده در Header، ترکیب Header کدگذاری شده، Payload کدگذاری شده، کلید مخفی و الگوریتم HMAC SHA256 ساخته میشود.
* در احراز هویت معمولا payload همان ماهیت کاربر است مثلا یوزرنیم و زمان انقضا در قالب JSON.
فرمول منطقی آن به این صورت است:
HMACSHA256(
base64UrlEncode(header) + "." + base64UrlEncode(payload),
secret
)
خروجی این محاسبه، رشته امضا خواهد بود. فرض کنیم:
SflKxwRJSMeKKF2QT4fwpMeJf36POk6yJV_adQssw5c
۴. مونتاژ نهایی توکن
در نهایت، این سه بخش را با یک نقطه (.) به هم میچسبانیم تا توکن نهایی ساخته شود:
eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJzdWIiOiIxMjM0NTY3ODkwIiwibmFtZSI6IkpvaG4gRG9lIiwiaWF0IjoxNTE2MjM5MDIyfQ.SflKxwRJSMeKKF2QT4fwpMeJf36POk6yJV_adQssw5c
پیادهسازی اولیه در پایتون (بدون کتابخانه JWT)
برای اینکه دقیقاً متوجه شوید چه اتفاقی در پشت صحنه میافتد، بیایید یک تابع ساده با استفاده از کتابخانه استاندارد base64 و hashlib بنویسیم. توجه داشته باشید که این کد صرفاً برای آموزش مفهوم است و در پروژه واقعی باید از کتابخانههای استاندارد استفاده کرد.
import base64
import hashlib
import hmac
import json
import time
def base64url_encode(data):
"""تبدیل رشته به فرمت Base64Url استاندارد"""
return base64.urlsafe_b64encode(data).rstrip(b'=').decode('utf-8')
def create_jwt(payload, secret):
# ۱. ساخت Header
header = {
"alg": "HS256",
"typ": "JWT"
}
# ۲. کدگذاری Header و Payload
header_encoded = base64url_encode(json.dumps(header).encode())
payload_encoded = base64url_encode(json.dumps(payload).encode())
# ۳. ساخت امضا (Signature)
message = f"{header_encoded}.{payload_encoded}"
signature = hmac.new(
secret.encode(),
message.encode(),
hashlib.sha256
).digest()
signature_encoded = base64url_encode(signature)
# ۴. ترکیب نهایی
jwt_token = f"{message}.{signature_encoded}"
return jwt_token
# مثال استفاده:
secret_key = "my_super_secret_key"
user_data = {
"user_id": ۱۲۳۴,
"username": "ali",
"exp": int(time.time()) + ۶۰ # انقضا بعد از ۶۰ ثانیه
}
token = create_jwt(user_data, secret_key)
print("توکن ساخته شده:")
print(token)
جمعبندی
در این مقاله یاد گرفتیم که یک JWT صرفاً یک رشته متنی است که از سه بخش کدگذاری شده تشکیل شده است. ما یاد گرفتیم چگونه با استفاده از توابع پایه پایتون، دادهها را کدگذاری کرده و با استفاده از یک کلید مخفی، روی آنها امضای دیجیتال بگذاریم.
در بخش دوم این سری آموزشی، نحوه پیادهسازی کامل احراز هویت در فریمورک فلسک را با استفاده از کتابخانههای استاندارد و امنتر بررسی خواهیم کرد و یاد میگیریم چگونه این توکن را در درخواستهای کاربر اعتبارسنجی کنیم.