احراز هویت حرفهای با JWT در فلسک
احراز هویت حرفهای با JWT در فلسک
PyJWT استفاده میکنیم تا یک سیستم احراز هویت کامل و امن را در فریمورک فلسک پیادهسازی کنیم.
نصب پیشنیازها
برای شروع، شما نیاز به نصب کتابخانه PyJWT دارید. اگر هنوز فلسک را نصب نکردهاید، آن را نیز اضافه کنید. دستور زیر را در ترمینال اجرا کنید:
pip install Flask PyJWT
تنظیمات اولیه و کلید مخفی
امنیت JWT به شدت به “کلید مخفی” (Secret Key) وابسته است. این کلید باید طولانی، پیچیده و کاملاً محرمانه باشد. در فلسک، معمولاً این کلید را در تنظیمات برنامه قرار میدهیم.
from flask import Flask, request, jsonify
import jwt
import datetime
from functools import wraps
app = Flask(__name__)
# کلید مخفی برای امضای توکنها
# در محیط واقعی، این مقدار باید از متغیرهای محیطی (Environment Variables) خوانده شود
app.config['SECRET_KEY'] = 'this_is_a_very_secure_secret_key_1234567890'
۱. ایجاد مسیر ورود (Login) و تولید توکن
اولین قدم، ایجاد یک مسیر است که کاربر نام کاربری و رمز عبور خود را ارسال میکند. اگر اطلاعات صحیح باشد، یک توکن JWT تولید شده و به کاربر بازگردانده میشود. این توکن باید شامل اطلاعات هویتی کاربر و زمان انقضا باشد.
@app.route('/login', methods=['POST'])
def login():
# دریافت اطلاعات ارسال شده توسط کاربر
auth = request.json
if not auth or not auth.get('username') or not auth.get('password'):
return jsonify({'message': 'نام کاربری و رمز عبور الزامی است'}), ۴۰۰
# در اینجا معمولاً چک کردن دیتابیس انجام میشود
# ما برای سادگی فرض میکنیم کاربر admin با رمز ۱۲۳۴۵ است
if auth['username'] == 'admin' and auth['password'] == '۱۲۳۴۵':
# تنظیم زمان انقضا (مثلاً ۳۰ دقیقه دیگر)
expiration_time = datetime.datetime.utcnow() + datetime.timedelta(minutes=۳۰)
# ساخت Payload توکن
payload = {
'user': auth['username'],
'exp': expiration_time # زمان انقضا (اختیاری اما توصیه شده)
}
# تولید توکن با استفاده از الگوریتم HS256
token = jwt.encode(payload, app.config['SECRET_KEY'], algorithm="HS256")
return jsonify({'token': token})
return jsonify({'message': 'نام کاربری یا رمز عبور اشتباه است'}), ۴۰۱
۲. ایجاد تابع محافظ (Decorator) برای احراز هویت
حالا که توکن را داریم، نیاز به راهی داریم تا مسیرهای محافظت شده (Protected Routes) را بسازیم. ما یک تابع دکوراتور مینویسیم که قبل از اجرای تابع اصلی مسیر، توکن ارسال شده در هدر درخواست (Header) را چک میکند.
def token_required(f):
@wraps(f)
def decorated(*args, **kwargs):
token = None
# توکن معمولاً در هدر Authorization با فرمت Bearer ارسال میشود
if 'Authorization' in request.headers:
auth_header = request.headers['Authorization']
try:
token = auth_header.split(" ")[۱] # جدا کردن توکن از کلمه Bearer
except IndexError:
return jsonify({'message': 'فرمت توکن نامعتبر است'}), ۴۰۱
if not token:
return jsonify({'message': 'توکن ارسال نشده است'}), ۴۰۱
try:
# تلاش برای دیکد کردن توکن و بررسی اعتبار آن
data = jwt.decode(token, app.config['SECRET_KEY'], algorithms=["HS256"])
current_user = data['user']
except jwt.ExpiredSignatureError:
return jsonify({'message': 'توکن منقضی شده است'}), ۴۰۱
except jwt.InvalidTokenError:
return jsonify({'message': 'توکن نامعتبر است'}), ۴۰۱
# ارسال کاربر شناسایی شده به تابع اصلی
return f(current_user, *args, **kwargs)
return decorated
۳. استفاده از مسیر محافظت شده
اکنون میتوانیم از دکوراتور token_required روی هر مسیری که نیاز به احراز هویت دارد استفاده کنیم. اگر کاربر توکن معتبر نداشته باشد، به محتوای مسیر دسترسی نخواهد داشت.
@app.route('/protected')
@token_required
def protected_route(current_user):
# این تابع فقط در صورتی اجرا میشود که توکن معتبر باشد
return jsonify({'message': f'سلام {current_user}! شما به یک منطقه محافظت شده دسترسی دارید.'})
۴. تست سیستم با Postman یا cURL
برای تست این سیستم، مراحل زیر را طی کنید:
- دریافت توکن: یک درخواست POST به آدرس
/loginبا بدنه JSON زیر ارسال کنید:{ "username": "admin", "password": "۱۲۳۴۵" }پاسخ شامل یک رشته طولانی (توکن) خواهد بود.
- دسترسی به مسیر محافظت شده: یک درخواست GET به آدرس
/protectedارسال کنید. در بخش Headers، کلیدAuthorizationرا اضافه کنید و مقدار آن را برابر باBearer YOUR_TOKEN_HEREقرار دهید.
نکات امنیتی مهم
- انتقال امن: همیشه سعی کنید توکنها را از طریق پروتکل HTTPS ارسال کنید تا در برابر حملات شنود (Man-in-the-Middle) محافظت شوند.
- ذخیرهسازی: توکنها را در سمت کلاینت (مرورگر) در
HttpOnly Cookiesذخیره کنید تا در برابر حملات XSS امن باشند. ذخیره در LocalStorage خطرات امنیتی دارد. - مدت زمان انقضا: همیشه برای توکنها زمان انقضا کوتاه (مثلاً ۱۵ دقیقه) تعیین کنید و از مکانیزم “تازهسازی توکن” (Refresh Token) برای جلسات طولانی استفاده کنید.
جمعبندی
در این بخش، یاد گرفتیم چگونه با استفاده از کتابخانه PyJWT در فلسک، یک سیستم احراز هویت مدرن و بدون وضعیت (Stateless) پیادهسازی کنیم. ما توکن را تولید کردیم، آن را اعتبارسنجی نمودیم و مسیرهای حساس را محافظت کردیم. این روش پایه و اساس اکثر APIهای مدرن امروزی است.