~3 دقیقه مطالعه • بروزرسانی ۲۴ اسفند ۱۴۰۴
مقدمه
یکی از اصول طلایی امنیت وب این است که هرگز به دادههای منبع نامطمئن اعتماد نکنید. گاهی لازم است دادهها را از طریق کانالهای نامطمئن (مثل URL، کوکیها یا فرمها) منتقل کنیم. سیستم امضای رمزنگاریشدهٔ جنگو این امکان را فراهم میکند که دادهها را بهصورت امن منتقل کنیم و مطمئن باشیم هرگونه دستکاری شناسایی خواهد شد.
جنگو دو سطح API ارائه میدهد:
- API سطح پایین برای امضای دادهها
- API سطح بالا برای کوکیهای امضاشده
کاربردهای رایج:
- لینکهای بازیابی رمز عبور
- محافظت از دادههای فرمهای مخفی
- لینکهای یکبارمصرف برای دانلود فایلهای محافظتشده
- ارسال امن داده از طریق کانالهای نامطمئن
محافظت از SECRET_KEY و SECRET_KEY_FALLBACKS
در پروژههای جدید، جنگو یک SECRET_KEY تصادفی تولید میکند.
این کلید برای امضای دادهها استفاده میشود و باید کاملاً محرمانه بماند.
SECRET_KEY_FALLBACKS برای چرخش کلیدها استفاده میشود:
کلیدهای fallback فقط برای اعتبارسنجی استفاده میشوند، نه امضا.
استفاده از API سطح پایین
برای امضای یک مقدار:
from django.core.signing import Signer
signer = Signer()
value = signer.sign("My string")
# خروجی: 'My string:signature'
برای بازیابی مقدار اصلی:
original = signer.unsign(value)
امضای مقادیر غیررشتهای
مقادیر قبل از امضا به رشته تبدیل میشوند:
signed = signer.sign(2.5)
signer.unsign(signed) # '2.5'
امضای ساختارهای پیچیده
برای امضای dict، list یا tuple:
signed_obj = signer.sign_object({"message": "Hello!"})
obj = signer.unsign_object(signed_obj)
در صورت دستکاری، استثنای BadSignature رخ میدهد.
استفاده از کلید سفارشی
میتوانید کلید امضا را تغییر دهید:
signer = Signer(key="my-other-secret")
استفاده از salt
اگر نمیخواهید امضای یک مقدار همیشه یکسان باشد، از salt استفاده کنید:
signer = Signer(salt="extra")
signer.sign("My string")
salt باعث ایجاد «فضاهای نام» مختلف برای امضاها میشود. امضای تولیدشده با یک salt در فضای salt دیگر معتبر نیست.
salt نیازی به محرمانه بودن ندارد.
امضای زماندار با TimestampSigner
TimestampSigner یک timestamp به امضا اضافه میکند تا بتوانید اعتبار زمانی تعیین کنید.
from django.core.signing import TimestampSigner
from datetime import timedelta
signer = TimestampSigner()
value = signer.sign("hello")
signer.unsign(value, max_age=10) # SignatureExpired
signer.unsign(value, max_age=20) # OK
همچنین میتوانید ساختارهای پیچیده را با timestamp امضا کنید:
signer.sign_object({"foo": "bar"})
محافظت از ساختارهای پیچیده
توابع dumps() و loads() میانبُرهایی برای امضای زماندار هستند:
from django.core import signing
value = signing.dumps({"foo": "bar"})
signing.loads(value)
این توابع از JSON استفاده میکنند، بنابراین خطرات pickle را ندارند. توجه: tupleها پس از loads به list تبدیل میشوند.
توابع مهم
- sign(): امضای رشته
- unsign(): اعتبارسنجی و بازیابی مقدار
- sign_object(): امضای dict/list/tuple
- unsign_object(): بازیابی ساختار
- dumps(): سریالسازی + timestamp + امضا
- loads(): اعتبارسنجی + بازیابی
جمعبندی
سیستم امضای رمزنگاریشدهٔ جنگو ابزاری قدرتمند برای انتقال امن داده از طریق کانالهای نامطمئن است.
با استفاده از Signer، TimestampSigner، dumps() و loads() میتوانید از یکپارچگی دادهها مطمئن شوید، دستکاری را تشخیص دهید و ساختارهای پیچیده را بهصورت امن مدیریت کنید.
نوشته و پژوهش شده توسط دکتر شاهین صیامی