بذار خیلی ساده شروع کنیم. اگه تا حالا با اودو کار کرده باشی، مخصوصا وقتی خواستی یه فرم بسازی، حتما اسم CSRF Token به گوشت خورده. اولش شاید فکر کنی یه فیلد اضافیه که باید بذاری توی فرم، ولی واقعیت اینه که این توکن مثل نگهبان جلوی دره. هر کسی بخواد وارد بشه، باید کارت ورود معتبر داشته باشه. این کارت همون CSRF Token هست.
چرا CSRF مهمه؟
حمله CSRF (Cross-Site Request Forgery) یعنی یه نفر از بیرون بخواد کاربر رو مجبور کنه یه درخواست جعلی بفرسته. مثلا کاربر لاگین کرده، مهاجم یه فرم جعلی میسازه که وقتی کاربر روش کلیک کنه، یه درخواست POST به سرور میره و مثلا یه رکورد حذف میشه. بدون CSRF Token، سرور نمیفهمه این درخواست واقعی بوده یا نه. پس این توکن مثل یه امضای دیجیتالیه که میگه "این درخواست واقعا از مرورگر کاربر اومده".
مرحله ۱: تولید سشن
خب، اولین چیزی که باید بدونی اینه که اودو برای هر درخواست یه سشن درست میکنه. حتی اگه کاربر لاگین نکرده باشه، باز هم یه سشن عمومی براش ساخته میشه. این سشن توی کوکی مرورگر ذخیره میشه و شامل چیزای مهمیه مثل:
- شناسه کاربر (
uid) اگه لاگین کرده باشه - زبان کاربر
- پایگاه داده انتخابی
- و البته
CSRF Token
این کار توسط SessionMiddleware توی ماژول odoo.http انجام میشه. اگه کوکی وجود داشته باشه، همونو بر میداره. اگه نه، یه سشن جدید میسازه.
مرحله ۲: تولید CSRF Token
وقتی سشن ساخته شد، یه توکن تصادفی هم تولید میشه. این توکن به همون سشن وصله. توی سرور میتونی با request.csrf_token بهش دسترسی داشته باشی. توی فرانتاند هم اودو خودش اینو توی فرمها به صورت hidden field میذاره:
<input type="hidden" name="csrf_token" t-att-value="request.csrf_token()"/>
اگه با جاوا اسکریپت کار میکنی، باید از odoo.csrf_token که توی اون odoo یه global object هست استفاده کنی و همراه درخواست AJAX بفرستی.
مرحله ۳: ارسال درخواست
وقتی کاربر فرم رو ارسال میکنه یا یه درخواست AJAX میفرسته، این توکن همراه دادهها میره سمت سرور. اینجاست که ماجرا جذاب میشه.
مرحله ۴: بررسی CSRF در dispatch
اینجا خیلی مهمه. بررسی CSRF داخل کنترلر انجام نمیشه، بلکه توی لایه dispatch توی odoo.http انجام میشه. یعنی قبل از اینکه کنترلر اصلا اجرا بشه، اودو میاد چک میکنه:
- آیا
route تعریف شدهcsrf=True داره؟ (پیشفرض همهroute ها همینه) - اگه درخواست
POST باشه وcsrf=True فعال باشه:- مقدار
csrf_token از دادههای درخواست خونده میشه - با مقدار ذخیره شده توی سشن مقایسه میشه
- مقدار
- اگه معتبر باشه → کنترلر اجرا میشه
- اگه نامعتبر باشه → خطای
403 Forbidden – CSRF validation failedبرمیگرده
مثال کاربردی: کنترلر با CSRF فعال
from odoo import http
class MyController(http.Controller):
@http.route('/my/form', type='http', auth='public', methods=['POST'], csrf=True)
def my_form(self, **post):
return "Form submitted successfully!"
اینجا اگه توکن درست باشه، کنترلر اجرا میشه. اگه نباشه، اصلا به اینجا نمیرسه.
مثال کاربردی: کنترلر بدون CSRF
from odoo import http
class MyAPI(http.Controller):
@http.route('/api/data', type='json', auth='public', csrf=False)
def api_data(self, **kwargs):
return {"status": "ok"}
این حالت برای API های عمومی استفاده میشه. ولی باید خیلی مراقب باشی چون امنیت پایین میاد.
چرا بررسی قبل از کنترلر انجام میشه؟
این طراحی خیلی هوشمندانه است. چون باعث میشه امنیت به صورت مرکزی مدیریت بشه. توسعه دهنده لازم نیست توی هر کنترلر جداگانه بررسی کنه. همه چیز قبل از رسیدن به کنترلر چک میشه.
نکات طلایی برای توسعه دهنده ها
- همیشه توی فرم های
QWeb ازrequest.csrf_token استفاده کن - توی جاوااسکریپت مقدار
csrf_token رو از آبجکت گلوبالodoo بگیر - فقط وقتی واقعا لازمه از
csrf=False استفاده کن - اگه خطای
"CSRF validation failed" دیدی، احتمالا توکن ارسال نشده یا با سشن مطابقت نداره
خلاصه CSRF Token توی اودو مثل یه نگهبان جلوی دره. هر درخواست باید کارت ورود معتبر داشته باشه. این کارت توی سشن ساخته میشه و قبل از رسیدن به کنترلر بررسی میشه. همین باعث میشه امنیت سیستم خیلی بالا بره و جلوی حملات CSRF گرفته بشه.