فصل ۱۹ — بهینهسازی و امنیت در Django

۱. مقدمه — چرا امنیت و بهینهسازی مهم است؟
در هر وبسایت یا API، دو چالش اصلی داریم:
- امنیت → جلوگیری از نفوذ، سرقت داده یا تغییر غیرمجاز.
- بهینهسازی (Performance) → افزایش سرعت و کاهش مصرف منابع سرور.
مشکل رایج در پروژههای واقعی:
- هکرها حملات XSS, CSRF, SQL Injection انجام میدهند.
- سایت کند میشود به دلیل کوئریهای سنگین یا استفاده زیاد از دیتابیس.
- منابع (CPU, RAM) بیخود مصرف میشوند چون هیچ Caching یا فایل استاتیک بهینهای استفاده نشده.
۲. اصول امنیت در Django
جنگو خودش خیلی از موارد امنیتی رو پیشفرض فعال کرده، مثل:
- جلوگیری از SQL Injection (از طریق ORM)
- جلوگیری از CSRF (با Middleware داخلی)
- رمزنگاری رمز عبور کاربر
اما باید این نکات رو رعایت کنیم:
۲.۱ جلوگیری از SQL Injection
ORM جنگو ذاتاً امنه ولی اگه از Raw SQL استفاده کنیم، باید همیشه پارامترها رو ایمن کنیم.
مثال اشتباه:
# خطرناک!
Product.objects.raw(f"SELECT * FROM store_product WHERE id={product_id}")
روش امن:
Product.objects.raw("SELECT * FROM store_product WHERE id = %s", [product_id])
📌 بهترین حالت: از ORM استفاده کن:
product = Product.objects.get(id=product_id)
۲.۲ جلوگیری از XSS (Cross-Site Scripting)
XSS یعنی تزریق کد جاوااسکریپت توسط کاربر و اجرای آن در مرورگر دیگران.
جنگو به صورت پیشفرض دادهها رو در قالب HTML escape میکنه:
{{ user_input }}
ولی اگر |safe استفاده کنی، مراقب باش فقط روی دادههای مطمئن باشه:
{{ trusted_content|safe }}
۲.۳ جلوگیری از CSRF (Cross-Site Request Forgery)
CSRF یعنی درخواست جعلی از طرف کاربر بدون اطلاعش.
در جنگو برای هر فرم:
<form method="post">
{% csrf_token %}
<!-- فیلدها -->
</form>
📌 برای APIها باید از CSRF exemption یا روشهای امن دیگر مثل Token Auth استفاده کنیم.
۲.۴ مدیریت رمز عبور
رمزها باید هش شده ذخیره شوند (جنگو این کار رو با PBKDF2 + SHA256 انجام میده).
وقتی کاربر رمز وارد میکنه:
from django.contrib.auth.hashers import make_password
user.password = make_password(raw_password)
📌 هرگز رمز رو در متن ساده ذخیره نکن.
۲.۵ محدود کردن تعداد تلاش (Login Attempt)
برای جلوگیری از Brute Force Attack میتوانیم از کتابخانههایی مثل:
pip install django-axes
این کتابخانه بعد از چند تلاش ناموفق کاربر رو بلاک میکنه.
۳. اصول بهینهسازی در Django
بهینهسازی یعنی کم کردن حجم پردازش و تعداد درخواستها تا سرعت سایت زیاد بشه.
۳.۱ استفاده از Query بهینه
اشتباه رایج:
for order in Order.objects.all():
print(order.customer.name) # باعث 1 کوئری برای هر سفارش میشه!
🔴 این همون مشکل N+1 Query هست.
روش بهینه با select_related:
orders = Order.objects.select_related('customer').all()
for order in orders:
print(order.customer.name)
برای ManyToMany یا ForeignKey معکوس:
products = Product.objects.prefetch_related('categories').all()
۳.۲ استفاده از Cache
کش کردن نتایج برای جلوگیری از فراخوانی مکرر دیتابیس.
در settings.py:
CACHES = {
'default': {
'BACKEND': 'django.core.cache.backends.locmem.LocMemCache',
'LOCATION': 'unique-snowflake'
}
}
در views.py:
from django.core.cache import cache
def get_featured_products():
products = cache.get('featured_products')
if not products:
products = Product.objects.filter(featured=True)
cache.set('featured_products', products, 3600) # یک ساعت
return products
📌 میتوان از Redis یا Memcached برای کش قویتر استفاده کرد.
۳.۳ استفاده از فایلهای استاتیک بهینه
- استفاده از Collectstatic برای جمع کردن فایلها
- فشردهسازی CSS و JS با ابزارهایی مثل
django-compressor - استفاده از CDN برای ارسال تصاویر و فایلها به کاربر
۳.۴ Pagination در دادهها
هرگز کل دادهها رو یکجا نده، از صفحهبندی استفاده کن (مثل فصل ۱۳).
۳.۵ استفاده از Background Tasks
کارهای سنگین رو در پسزمینه انجام بده:
- ارسال ایمیل
- پردازش تصویر
- گرفتن داده از API
📌 ابزار محبوب: Celery + Redis
۴. امنیت APIها
اگر پروژه شما API هم دارد:
- استفاده از احراز هویت امن (Token/JWT/OAuth2)
- محدود کردن درخواستها (Throttling)
# settings.py
REST_FRAMEWORK = {
'DEFAULT_THROTTLE_CLASSES': [
'rest_framework.throttling.UserRateThrottle',
],
'DEFAULT_THROTTLE_RATES': {
'user': '100/day'
}
}
- بررسی ورودیها قبل از ذخیره در دیتابیس
۵. جلوگیری از حملات رایج
| حمله | توضیح کوتاه | راهحل در Django |
|---|---|---|
| SQL Injection | تزریق کد SQL | استفاده از ORM |
| XSS | تزریق کد جاوااسکریپت | استفاده از escape پیشفرض |
| CSRF | درخواست جعلی | CSRF Token |
| Brute Force | تست مکرر رمز عبور | محدود کردن تلاشها |
| Clickjacking | فریب کاربر برای کلیک | اضافه کردن HTTP Header X-Frame-Options |
اضافه کردن هدر Clickjacking:
MIDDLEWARE += ['django.middleware.clickjacking.XFrameOptionsMiddleware']
X_FRAME_OPTIONS = 'DENY'
۶. امنسازی تنظیمات (settings.py)
- DEBUG=False در محیط واقعی
- نگهداری SECRET_KEY در
.env - محدود کردن
ALLOWED_HOSTS:
ALLOWED_HOSTS = ['yourdomain.com']
- فعال کردن HTTPS (با HSTS):
SECURE_HSTS_SECONDS = 31536000
SECURE_SSL_REDIRECT = True
۷. مانیتورینگ و لاگها
برای رصد مشکلات و حملات:
LOGGING = {
'version': 1,
'handlers': {
'file': {
'level': 'ERROR',
'class': 'logging.FileHandler',
'filename': 'errors.log',
},
},
'loggers': {
'django': {
'handlers': ['file'],
'level': 'ERROR',
'propagate': True,
},
},
}
📌 همیشه لاگها رو چک کن تا بفهمی کجا مشکل یا حمله رخ داده.
۸. بهینهسازی پرس و جوهای سنگین با Cache Template
اگر بخشی از صفحه همیشه تغییری نداره، میتونی کشش کنی:
{% load cache %}
{% cache 600 featured_products %}
{% for product in products %}
{{ product.name }}
{% endfor %}
{% endcache %}
📌 اینجا ۶۰۰ ثانیه کش میشه.
۹. سناریوی واقعی — فروشگاه آنلاین امن و سریع
مراحل:
- فیلتر کردن همه ورودیها (Form Validation)
- استفاده از ORM به جای Raw Query
- افزودن CSRF Token به فرمها
- فعالسازی HTTPS و محدود کردن ALLOWED_HOSTS
- اضافه کردن Cache برای محصولات پرفروش
- استفاده از Pagination برای لیست طولانی محصولات
- استفاده از Celery برای کارهای سنگین (ایمیل، پردازش تصویر)
- محدود کردن تلاش ورود با
django-axes - بررسی مرتب لاگها برای کشف حملات
۱۰. نتیجهگیری فصل ۱۹
الان یاد گرفتیم چطور:
- از حملات رایج مثل XSS و SQL Injection جلوگیری کنیم
- سرعت سایت رو با Cache، Query بهینه، و Background Tasks بالا ببریم
- تنظیمات امنیتی رو در محیط واقعی درست انجام بدیم
- API رو ایمن کنیم