محتوای آموزشی وبلاگ نتآرام
صفحه ورود یا فرم سایت جنگو باز میشود، اما بعد از زدن دکمه ثبت، خطای
403 CSRF verification failed میبینید. ممکن است همان فرم روی رایانه شما کار کرده باشد و بعد از انتقال به هاست یا فعالکردن HTTPS خطا بدهد. جنگو برای محافظت از کاربران بررسی میکند که درخواست تغییر اطلاعات از مسیر مورد انتظار آمده و نشانه امنیتی لازم را دارد. اگر یکی از این شرطها برقرار نباشد، درخواست را رد میکند.راهحل مناسب به علت دقیق پیام بستگی دارد: ممکن است توکن داخل فرم نباشد، مرورگر کوکی را نفرستد، مبدأ درخواست با نشانی مورد انتظار فرق کند یا تنظیم پراکسی نادرست باشد. در این راهنما مشکل را مرحلهبهمرحله جدا میکنیم. خاموشکردن CSRF یا گذاشتن یک تنظیم عمومی برای همه دامنهها، مشکل را پنهان میکند و حفاظت فرم را از بین میبرد.
پیش از شروع: یک فرم و آدرس مشخص را انتخاب کنید
یک فرم بیخطر در سایت خود انتخاب کنید و نشانی صفحه، زمان خطا و کاری را که انجام دادهاید یادداشت کنید. از حساب آزمایشی استفاده کنید تا چند بار امتحانکردن باعث ثبت سفارش یا تغییر داده واقعی نشود. مرورگر را در پنجره خصوصی هم امتحان کنید؛ اگر مشکل فقط در یک مرورگر است، کوکیهای همان سایت یا افزونههای آن سرنخ مهمی هستند.
در پنل هاست، برنامه پایتون و مسیر گزارشش را پیدا کنید. گزارش جنگو ممکن است علت دقیقتری مانند نبود کوکی، نبود توکن یا نامعتبر بودن Origin را نشان دهد. محل لاگ به شیوه اجرای سرویس بستگی دارد. کلیدها، کوکیها، رمزها و محتوای فرم را در تصویر یا گزارش عمومی قرار ندهید.
DEBUG را هم برای نمایش خطا روی سایت عمومی روشن نکنید.۱. توکن را داخل فرم داخلی قرار دهید
اگر فرم با قالب Django ساخته شده و به آدرس داخلی خود سایت با روش POST میرود، در فایل قالب مطمئن شوید تگ CSRF داخل همان فرم قرار دارد. نمونه ساده:
کد / دستور<form method="post" action="/contact/">
{% csrf_token %}
<label for="message">پیام</label>
<input id="message" name="message" required>
<button type="submit">ارسال</button>
</form>
این یک مثال است؛ مسیر و فیلدها باید مطابق پروژه شما باشند. وقتی قالب بهدرستی با زمینه درخواست رندر میشود، جنگو مقدار مناسب را در فرم قرار میدهد. اگر قالب را با
render معمول جنگو یا ابزارهای استانداردش رندر میکنید، معمولاً زمینه لازم فراهم است؛ در رندر سفارشی باید همان مسیر را بررسی کنید.این تگ را داخل فرمی که اطلاعات را به یک سایت خارجی میفرستد نگذارید، چون ممکن است توکن به آن مقصد داده شود. حذف
CsrfViewMiddleware یا استفاده بیدلیل از csrf_exempt راهحل این خطا نیست. پس از اصلاح قالب، تغییر را به روش معمول پروژه منتشر، برنامه را در صورت نیاز از پنل Restart و فرم آزمایشی را دوباره ارسال کنید.۲. کوکی و درخواست را در مرورگر ببینید
در مرورگر
F12 را بزنید و زبانه Network را باز کنید. یک بار صفحه فرم را بارگذاری و سپس فرم آزمایشی را ارسال کنید. روی درخواست ناموفق کلیک کنید. بررسی کنید درخواست واقعاً به دامنه و مسیر مورد انتظار رفته و پس از انتقال ناخواسته به دامنه دیگر نرسیده باشد. در زبانه مربوط به کوکیها، وجود کوکی CSRF و ارسال آن همراه درخواست را بررسی کنید؛ نام و تنظیم آن در پروژه ممکن است تغییر داده شده باشد.اگر مرورگر ذخیره کوکی را برای سایت بسته یا سیاست حریم خصوصی آن را رد کرده است، دلیل نشاندادهشده توسط مرورگر را بخوانید و با تنظیمات واقعی پروژه مقایسه کنید. پاککردن کوکی همین سایت و ورود دوباره میتواند نشست قدیمی یا ناسازگار را مشخص کند. اگر خطا پس از این کار برطرف شد، نسخه جدید فرم را نیز آزمایش کنید؛ توکن قدیمی صفحه بازمانده ممکن است دیگر با نشست تازه همخوان نباشد.
اگر فرم با JavaScript ارسال میشود، وجود تگ در HTML بهتنهایی کافی نیست. درخواست Ajax باید توکن معتبر را مطابق تنظیمات پروژه همراه داده یا سرآیند مناسب ارسال کند. در تنظیم پیشفرض، جنگو میتواند سرآیند
X-CSRFToken را بخواند. روش بهدستآوردن توکن به تنظیمات CSRF_COOKIE_HTTPONLY و ذخیره آن در نشست بستگی دارد؛ نمونه سازگار را از مستندات رسمی جنگو و نسخه پروژه انتخاب کنید. توکن را به دامنههای غیرمورداعتماد نفرستید.۳. نام دامنه، مبدأ و انتقالها را مقایسه کنید
مبدأ یا Origin از طرح اتصال، نام دامنه و در صورت وجود پورت تشکیل میشود.
http://example.com، https://example.com و https://app.example.com یک مبدأ یکسان نیستند. در Network، نشانی صفحه فرم و مقصد درخواست POST را مقایسه کنید. اگر کاربر فرم را روی یک دامنه باز میکند ولی درخواست به دامنه دیگری میرود، ابتدا مشخص کنید این طراحی عمدی و مورد اعتماد است یا بهخاطر تنظیم اشتباه آدرس برنامه رخ داده است.برای دیدن انتقال یک آدرس عمومی میتوانید از ترمینال رایانه یا سرور استفاده کنید:
کد / دستورcurl -I https://example.com/contact/
به جای نشانی نمونه، آدرس عمومی فرم خود را بگذارید. خط
Location در پاسخ انتقال، مقصد را نشان میدهد. این فرمان POST و CSRF را آزمایش نمیکند؛ فقط برای دیدن پاسخ سرآیند آن نشانی مفید است. اگر دامنه اصلی به www منتقل میشود، صفحه و مقصد فرم باید با طراحی واقعی سایت سازگار باشند.۴. مبدأ مورد اعتماد را فقط در صورت نیاز اضافه کنید
در Django نسخههای جدید، وقتی طراحی پروژه به پذیرش درخواست از یک مبدأ متفاوت و مورد اعتماد نیاز دارد، میتوان آن مبدأ مشخص را در تنظیمات قرار داد. برای نمونه، اگر واقعاً فرم از
کد / دستورhttps://forms.example.com به برنامه شما درخواست میفرستد:CSRF_TRUSTED_ORIGINS = [
"https://forms.example.com",
]
نام واقعی، طرح
https و در صورت استفاده از پورت غیراستاندارد، پورت صحیح را مطابق نسخه جنگو وارد کنید. این مثال مجوز کلی برای هر سایت نیست و جایگزین ارسال توکن یا کوکی معتبر نمیشود. افزودن دامنهای که نمیشناسید یا اعتماد گسترده به همه زیردامنهها میتواند امنیت را کم کند.این تنظیم با
ALLOWED_HOSTS متفاوت است. در ALLOWED_HOSTS نام میزبان برنامه را بدون https:// و مسیر مینویسید؛ در مبدأ مورد اعتماد، طرح اتصال بخشی از مقدار است. اگر خود صفحه ۴۰۰ و DisallowedHost میدهد، راهنمای رفع خطای میزبان جنگو را دنبال کنید. نسخههای قدیمیتر جنگو در قالب برخی تنظیمات تفاوت دارند؛ راهنمای همان نسخه را بخوانید.۵. اگر HTTPS در پراکسی تمام میشود
گاهی اتصال کاربر تا پراکسی با HTTPS است، اما پراکسی درخواست را از مسیر داخلی دیگری به جنگو میرساند. اگر برنامه از روش اتصال واقعی خبر نداشته باشد، تنظیمات امنیتی و تولید نشانیها میتوانند به مشکل بخورند. در هاست اشتراکی ابتدا از ارائهدهنده بپرسید آیا پراکسی مورد اعتماد هدر درست را خودش تنظیم میکند، هدر ارسالی کاربر را حذف میکند و آیا راه دسترسی مستقیم و دورزدن پراکسی بسته است یا نه.
جنگو گزینهای به نام
SECURE_PROXY_SSL_HEADER دارد، اما مقداردهی آن بدون اطمینان از موارد بالا خطرناک است: مهاجم ممکن است سرآیندی جعل کند و برنامه را درباره امن بودن اتصال به اشتباه بیندازد. این گزینه را فقط پس از تأیید طراحی پراکسی و طبق هشدار رسمی تنظیمات جنگو تنظیم کنید. لازم نیست برای هر خطای CSRF به آن دست بزنید.۶. دوباره فرم را به شکل واقعی آزمایش کنید
پس از ذخیره تنظیمات تأییدشده، برنامه مربوط را در پنل Restart کنید. یک صفحه فرم تازه باز کنید، با حساب آزمایشی آن را ارسال کنید و نتیجه را در Network و گزارش برنامه ببینید. موفقیت یعنی هم پاسخ مناسب برگشته و هم عمل مورد انتظار فقط یک بار انجام شده است. اگر همچنان ۴۰۳ میگیرید، علت ثبتشده را با همان مرحله تطبیق دهید؛ خطای نبود توکن با خطای Origin راهحل یکسان ندارد.
اگر درخواست بین دامنهها با Fetch انجام میشود، تنظیم CORS و ارسال مجاز کوکی نیز جداگانه مطرحاند. بازکردن CORS برای همه دامنهها یا خاموشکردن CSRF راهحل مناسب نیست. برای اجرای پروژههای سازگار، صفحه هاست پایتون نتآرام و برای جزئیات فرمها راهنمای رسمی CSRF جنگو را ببینید.
برچسبها:
اشتراکگذاری:
لینکدینتلگرامایکس
مقاله قبلی
مقاله بعدی
دیدگاهها (۰)
دیدگاههای تاییدشده و پاسخهای تیم نتآرام
