تغییرات اخیر

در اینجا اطلاعیه‌ها، نسخه‌ها و تغییرات جدید لیارا فهرست می‌شوند.

چگونه امنیت پروژه Django در محیط تولید را افزایش دهیم؟


۱۵ آبان ۱۴۰۴

توسعه یک اپلیکیشن با Django می‌تواند تجربه‌ای راحت و انعطاف‌پذیر باشد، چون این فریم‌ورک به گونه‌ای طراحی شده که مقیاس‌پذیری بالایی داشته باشد. این ویژگی حتی به تنظیمات امنیتی Django هم سرایت کرده و کمک می‌کند پروژه‌تان را برای محیط تولید آماده کنید. اما راه‌های بیشتری برای افزایش امنیت وجود دارد که می‌توانید از آن‌ها بهره ببرید.

یکی از بهترین روش‌ها، تقسیم تنظیمات پروژه است تا بتوانید پیکربندی‌های متفاوتی برای محیط‌های مختلف ایجاد کنید. استفاده از فایل .env برای ذخیره متغیرهای محیطی یا پنهان کردن اطلاعات حساس، تضمین می‌کند که هیچ جزئیات محرمانه‌ای افشا نشود و پروژه‌تان در امان بماند. همچنین، تغییر URLهای پیش‌فرض و سایر تنظیمات، از آسیب‌پذیری‌های رایج جلوگیری می‌کند.

هرچند در ابتدا پیاده‌سازی این استراتژی‌ها ممکن است زمان‌بر به نظر برسد، اما با ایجاد یک جریان کاری عملی، می‌توانید نسخه‌های جدید پروژه را بدون کاهش امنیت یا بهره‌وری مستقر کنید.

در این راهنما، شما یک جریان کاری امنیتی برای پروژه Django خود پیاده‌سازی خواهید کرد. این شامل تنظیمات مبتنی بر محیط، استفاده از .env و ویژگی‌های امنیتی داخلی Django می‌شود. این عناصر با هم ترکیب می‌شوند و پروژه‌ای آماده برای روش‌های مختلف استقرار ایجاد می‌کنند.

هاست Django، بدون نیاز به پیکربندی و انجام تنظیمات، به‌راحتی وب‌سایت خود را راه‌اندازی کنید.
✅ دامنه‌ رایگان ✅ ترافیک نامحدود ✅ هزینه ساعتی
خرید هاست ابری Django

آنچه در ادامه خواهید خواند:

  • پیش‌نیازها
  • گام اول: بازسازی تنظیمات Django
  • گام دوم: استفاده از django-environ
  • گام سوم: ایجاد تنظیمات توسعه و تولید
  • گام چهارم: کار با تنظیمات امنیتی Django
  • گام پنجم: استفاده از django-environ برای اسرار
  • جمع بندی

پیش‌نیازها

قبل از شروع، موارد زیر را آماده کنید:

  • یک پروژه Django موجود. اگر هنوز پروژه‌ای ندارید، می‌توانید از راهنمای نحوه نصب Django و تنظیم محیط توسعه استفاده کنید. در آن راهنما، از پروژه testsite به عنوان مثال استفاده شده است.
  • Python 3 نصب‌شده روی سیستم. برای نصب، گام اول راهنمای نحوه نصب Python 3 را دنبال کنید.
  • گواهی Let’s Encrypt. اگر هنوز تنظیم نکرده‌اید، راهنمای نحوه امن کردن Nginx با Let’s Encrypt را ببینید.
  • برای استفاده از گواهی Let’s Encrypt، به Nginx نیاز دارید. راهنمای نحوه نصب Nginx روی Ubuntu 20.04 را برای نصب دنبال کنید.
  • سری راهنماهای توسعه Django عالی است برای آشنایی با ساختار فایل‌ها و تنظیمات اصلی Django. توجه: اگر از یک پروژه Django موجود استفاده می‌کنید، ممکن است نیازهای متفاوتی داشته باشید. این راهنما ساختار خاصی پیشنهاد می‌دهد، اما می‌توانید هر بخش را جداگانه اعمال کنید.

گام اول: بازسازی تنظیمات Django

قبل از ورود به جزئیات امنیتی، به دایرکتوری پروژه بروید و محیط مجازی را فعال کنید:

cd django-apps
. env/bin/activate

در این گام اول، فایل settings.py را به تنظیمات خاص محیطی تقسیم می‌کنیم. این روش عالی است وقتی پروژه را بین محیط‌های مختلف جابه‌جا می‌کنید، مثل توسعه و تولید. این کار باعث می‌شود نیاز به تغییرات زیاد نداشته باشید؛ به جای آن، از یک متغیر محیطی برای سوئیچ بین پیکربندی‌ها استفاده می‌کنید که بعداً توضیح می‌دهم.

یک دایرکتوری جدید به نام settings در زیردایرکتوری پروژه ایجاد کنید:

mkdir testsite/testsite/settings

(طبق پیش‌نیازها، از testsite استفاده می‌کنیم، اما نام پروژه خودتان را جایگزین کنید.)

این دایرکتوری جایگزین فایل settings.py فعلی می‌شود؛ تمام تنظیمات محیطی در فایل‌های جداگانه داخل این پوشه قرار می‌گیرند.

داخل پوشه settings جدید، سه فایل پایتون بسازید:

cd testsite/testsite/settings
touch base.py development.py production.py

فایل development.py شامل تنظیماتی است که معمولاً در توسعه استفاده می‌کنید. production.py برای سرور تولید است. این دو را جدا نگه دارید چون تولید به تنظیماتی نیاز دارد که در توسعه کار نمی‌کنند؛ مثل اجبار به HTTPS، اضافه کردن هدرها و استفاده از پایگاه داده تولید.

فایل base.py تنظیمات مشترکی دارد که development.py و production.py از آن ارث‌بری می‌کنند. این کار تکرار کد را کم می‌کند و کد را تمیز نگه می‌دارد. این فایل‌ها جایگزین settings.py می‌شوند، پس settings.py را حذف کنید تا Django گیج نشود.

هنوز در دایرکتوری settings، فایل settings.py را به base.py تغییر نام دهید:

mv ../settings.py base.py

حالا ساختار تنظیمات محیطی جدید را آماده کرده‌اید. اما پروژه هنوز این تغییرات را نمی‌شناسد، پس در گام بعدی این را درست می‌کنیم.

گام دوم: استفاده از django-environ

در حال حاضر، Django پوشه تنظیمات جدید و فایل‌های داخل آن را نمی‌شناسد. پس قبل از ادامه، باید Django را با django-environ سازگار کنید. این وابستگی متغیرهای محیطی را از فایل .env بارگذاری می‌کند. یعنی Django به فایل .env در ریشه پروژه نگاه می‌کند تا تصمیم بگیرد کدام پیکربندی تنظیمات را استفاده کند.

به ریشه پروژه بروید و محتوای دایرکتوری را با ls ببینید:

cd ../../
ls

فایل‌ها باید چیزی شبیه این باشند:

Output
db.sqlite3  manage.py  testsite

django-environ را نصب کنید:

pip install django-environ

حالا Django را برای استفاده از .env پیکربندی کنید. دو فایل را ویرایش می‌کنیم: manage.py برای توسعه و wsgi.py برای تولید.

ابتدا manage.py را باز کنید:

nano manage.py

کد برجسته‌شده زیر را اضافه کنید:

testsite/manage.py
import os
import sys
import environ

environ.Env.read_env()

def main():
    os.environ.setdefault('DJANGO_SETTINGS_MODULE', 'testsite.settings')

    try:
        from django.core.management import execute_from_command_line
    except ImportError as exc:
        raise ImportError(
            "Couldn't import Django. Are you sure it's installed and "
            "available on your PYTHONPATH environment variable? Did you "
            "forget to activate a virtual environment?"
        ) from exc
    execute_from_command_line(sys.argv)


if __name__ == '__main__':
    main()

فایل را ذخیره و ببندید (CTRL+X، Y، ENTER).

حالا wsgi.py را باز کنید:

nano testsite/wsgi.py

خطوط برجسته‌شده را اضافه کنید:

testsite/testsite/wsgi.py

import os
import environ

environ.Env.read_env()

from django.core.wsgi import get_wsgi_application

os.environ.setdefault('DJANGO_SETTINGS_MODULE', 'testsite.settings')

application = get_wsgi_application()

فایل را ذخیره و ببندید.

این کد دو کار می‌کند: هر بار که Django اجرا می‌شود (manage.py برای توسعه، wsgi.py برای تولید)، به دنبال .env می‌گردد. اگر فایل وجود داشته باشد، از پیکربندی پیشنهادی آن استفاده می‌کند؛ در غیر این صورت، به توسعه پیش‌فرض برمی‌گردد.

در نهایت، فایل .env را در دایرکتوری فعلی بسازید:

nano .env

خط زیر را اضافه کنید تا محیط را به توسعه تنظیم کند:

testsite/.env
DJANGO_SETTINGS_MODULE="testsite.settings.development"

فایل را ذخیره و ببندید.

توجه: .env را به .gitignore اضافه کنید تا در کامیت‌ها وارد نشود؛ این فایل برای داده‌های حساس مثل رمزها و کلیدهای API است. هر محیطی .env خودش را خواهد داشت.

به طور پیش‌فرض، Django از testsite.settings.development استفاده می‌کند، اما اگر DJANGO_SETTINGS_MODULE را به testsite.settings.production تغییر دهید، به پیکربندی تولید سوئیچ می‌شود. حالا development.py و production.py را پر کنید.

گام سوم: ایجاد تنظیمات توسعه و تولید

حالا base.py را باز کنید و تنظیماتی که می‌خواهید برای هر محیط تغییر دهید، به فایل‌های جداگانه منتقل کنید. production.py به اعتبارهای پایگاه داده تولید نیاز دارد، پس آن‌ها را آماده کنید.

توجه: تصمیم‌گیری در مورد تنظیمات محیطی به شما بستگی دارد. این راهنما فقط مثال‌های رایج مثل تنظیمات امنیتی و پیکربندی پایگاه داده جداگانه را پوشش می‌دهد.

در این مثال، از پروژه پیش‌نیاز استفاده می‌کنیم. تنظیمات را از base.py به development.py منتقل کنید. development.py را باز کنید:

nano testsite/settings/development.py

کد زیر را اضافه کنید:

testsite/testsite/settings/development.py
import os
from .base import *

DEBUG = True

DATABASES = {
    'default': {
        'ENGINE': 'django.db.backends.sqlite3',
        'NAME': os.path.join(BASE_DIR, 'db.sqlite3'),
    }
}

فایل را ذخیره و ببندید.

ابتدا از base.py وارد می‌کنید — این فایل تنظیمات را ارث می‌برد. سپس تنظیمات خاص توسعه را منتقل می‌کنید: DEBUG روی True (که در تولید نباید باشد) و DATABASES برای پایگاه داده محلی (اینجا SQLite برای توسعه).

توجه: برای امنیت، خروجی DEBUG Django هرگز تنظیماتی با رشته‌هایی مثل API، KEY، PASS، SECRET، SIGNATURE یا TOKEN را نشان نمی‌دهد.

این برای جلوگیری از افشای اسرار است اگر اشتباها با DEBUG روشن مستقر کنید.

هرگز با DEBUG روشن پروژه را عمومی نکنید؛ فقط امنیت را به خطر می‌اندازد.

حالا production.py را اضافه کنید. فایل را باز کنید:

nano testsite/settings/production.py

کد زیر را اضافه کنید. شبیه development.py است اما با پیکربندی پایگاه داده متفاوت و DEBUG روی False:

testsite/testsite/settings/production.py
import os
from .base import *
import environ

env = environ.Env()
environ.Env.read_env()

DEBUG = False

ALLOWED_HOSTS = []

DATABASES = {
    'default': {
        'ENGINE': env('SQL_ENGINE', default='django.db.backends.sqlite3'),
        'NAME': env('SQL_DATABASE', default=os.path.join(BASE_DIR, 'db.sqlite3')),
        'USER': env('SQL_USER', default='user'),
        'PASSWORD': env('SQL_PASSWORD', default='password'),
        'HOST': env('SQL_HOST', default='localhost'),
        'PORT': env('SQL_PORT', default=''),
    }
}

فایل را ذخیره و ببندید.

در این مثال، از .env برای پیکربندی اعتبارها با پیش‌فرض‌ها استفاده می‌کنید. اگر پایگاه داده تولید تنظیم کرده‌اید، از پیکربندی خودتان استفاده کنید.

حالا پروژه بر اساس DJANGO_SETTINGS_MODULE در .env تنظیمات متفاوت استفاده می‌کند. مثلاً در تولید، DEBUG خاموش می‌شود، ALLOWED_HOSTS تعریف می‌شود و از پایگاه داده سرور استفاده می‌کنید.

گام چهارم: کار با تنظیمات امنیتی Django

Django تنظیمات امنیتی آماده‌ای دارد که می‌توانید اضافه کنید. در این گام، تنظیمات ضروری برای تولید اضافه می‌کنید. این‌ها برای وقتی پروژه عمومی است، و نه برای توسعه توصیه می‌شود؛ پس آن‌ها را فقط به production.py محدود کنید.

این تنظیمات عمدتاً HTTPS را برای ویژگی‌هایی مثل کوکی‌های جلسه، کوکی‌های CSRF، ارتقای HTTP به HTTPS و غیره اجبار می‌کنند. اگر سرور با دامنه تنظیم نشده، این بخش را بعداً انجام دهید. برای آماده‌سازی سرور، نتیجه‌گیری را برای مقالات پیشنهادی ببینید.

ابتدا production.py را باز کنید:

nano testsite/settings/production.py

تنظیمات برجسته‌شده را اضافه کنید که برای پروژه‌تان مناسب باشد، طبق توضیحات بعد از کد:

testsite/testsite/settings/production.py
import os
from .base import *
import environ

env = environ.Env()
environ.Env.read_env()

DEBUG = False

ALLOWED_HOSTS = ['your_domain', 'www.your_domain']

DATABASES = {
    'default': {
        'ENGINE': env('SQL_ENGINE', default='django.db.backends.sqlite3'),
        'NAME': env('SQL_DATABASE', default=os.path.join(BASE_DIR, 'db.sqlite3')),
        'USER': env('SQL_USER', default='user'),
        'PASSWORD': env('SQL_PASSWORD', default='password'),
        'HOST': env('SQL_HOST', default='localhost'),
        'PORT': env('SQL_PORT', default=''),
    }
}

SECURE_SSL_REDIRECT = True

SESSION_COOKIE_SECURE = True

CSRF_COOKIE_SECURE = True

SECURE_BROWSER_XSS_FILTER = True
  • ALLOWED_HOSTS لیستی از نام‌های هاست/دامنه است که پروژه می‌تواند سرو کند. این برای جلوگیری از مسموم کردن کش و DNS است. جزئیات بیشتر در مستندات Django.
  • SECURE_SSL_REDIRECT همه درخواست‌های HTTP را به HTTPS هدایت می‌کند (مگر موارد استثنا). پروژه همیشه از اتصال رمزنگاری‌شده استفاده می‌کند. SSL روی سرور لازم است. اگر Nginx یا Apache این کار را می‌کنند، این تنظیم اضافی است.
  • SESSION_COOKIE_SECURE به مرورگر می‌گوید کوکی‌ها فقط روی HTTPS کار کنند. کوکی‌های فعالیت‌هایی مثل لاگین فقط روی اتصال امن کار می‌کنند.
  • CSRF_COOKIE_SECURE شبیه قبلی است اما برای توکن CSRF. این از جعل درخواست‌های کراس‌سایت جلوگیری می‌کند و تضمین می‌کند فرم‌ها (لاگین، ثبت‌نام) از پروژه خودتان هستند.
  • SECURE_BROWSER_XSS_FILTER هدر X-XSS-Protection: 1; mode=block را روی پاسخ‌ها تنظیم می‌کند. این از تزریق اسکریپت توسط دیگران جلوگیری می‌کند. مثلاً اگر کاربری اسکریپت در پایگاه داده ذخیره کند، وقتی نمایش داده شود اجرا نمی‌شود.

فایل را ذخیره و ببندید.

برای اطلاعات بیشتر در مورد تنظیمات امنیتی Django، مستندات‌شان را ببینید.

هشدار: مستندات Django می‌گوید کاملاً به SECURE_BROWSER_XSS_FILTER تکیه نکنید. همیشه ورودی‌ها را اعتبارسنجی و پاک‌سازی کنید.

تنظیمات اضافی

تنظیمات زیر برای پشتیبانی از HTTP Strict Transport Security (HSTS) هستند — یعنی کل سایت همیشه باید SSL استفاده کند.

  • SECURE_HSTS_SECONDS زمان HSTS در ثانیه است. اگر یک ساعت تنظیم کنید، هر بازدیدی به مرورگر می‌گوید برای آن ساعت فقط HTTPS مجاز است. اگر بخشی ناامن بازدید شود، خطا نشان می‌دهد.
  • SECURE_HSTS_PRELOAD اگر SECURE_HSTS_SECONDS تنظیم شده باشد کار می‌کند. این سایت را برای پیش‌بارگذاری در لیست سخت‌کد شده مرورگرها مثل فایرفاکس و کروم اضافه می‌کند. سایت همیشه باید رمزنگاری‌شده باشد. مراقب باشید؛ اگر بعداً رمزنگاری را بردارید، حذف از لیست هفته‌ها طول می‌کشد.
  • SECURE_HSTS_INCLUDE_SUBDOMAINS HSTS را به همه زیردامنه‌ها اعمال می‌کند. یعنی both your_domain و unsecure.your_domain نیاز به رمزنگاری دارند، حتی اگر unsecure.your_domain به این پروژه مربوط نباشد.

هشدار: پیکربندی نادرست این تنظیمات می‌تواند سایت را برای مدت طولانی خراب کند.

قبل از پیاده‌سازی، مستندات HSTS Django را بخوانید.

این تنظیمات را بر اساس پروژه خود ارزیابی کنید؛ این پیکربندی پایه خوبی برای بیشتر پروژه‌های Django است. حالا به استفاده بیشتر از .env می‌پردازیم.

گام پنجم: استفاده از django-environ برای اسرار

بخش نهایی، بهره‌برداری بیشتر از django-environ است. این به پنهان کردن اطلاعاتی مثل SECRET_KEY پروژه یا URL ادمین کمک می‌کند. عالی برای انتشار کد روی GitHub یا GitLab، چون اسرار منتشر نمی‌شوند. در عوض، هر بار پروژه را روی محیط محلی یا سرور تنظیم می‌کنید، .env جدید بسازید و متغیرهای secret را تعریف کنید.

SECRET_KEY را باید پنهان کنید، پس از آن شروع می‌کنیم.

.env در ریشه پروژه را باز کنید:

nano .env

خط زیر را اضافه کنید و your_secret_key را با رشته امن خود جایگزین کنید:

testsite/.env
DJANGO_SETTINGS_MODULE="testsite.settings.development"
SECRET_KEY="your_secret_key"

فایل را ذخیره و ببندید.

حالا base.py را باز کنید:

nano testsite/settings/base.py

متغیر SECRET_KEY را بروزرسانی کنید:

testsite/testsite/settings/base.py
. . .
import environ

env = environ.Env()
environ.Env.read_env()

SECRET_KEY = env('SECRET_KEY')
. . .

توجه: SECRET_KEY را با کلید واقعی جایگزین نکنید. متغیر همان بماند و کلید واقعی در .env برود.

فایل را ذخیره و ببندید. پروژه حالا SECRET_KEY از .env استفاده می‌کند.

در نهایت، URL ادمین را با اضافه کردن رشته‌ای طولانی از کاراکترهای تصادفی پنهان کنید. به جای your_domain/admin، به your_domain/very_secret_url/admin بروید. این کار پیدا کردن URL ادمین را برای بات‌ها و افراد غریبه سخت می‌کند و brute force را دشوارتر.

.env را دوباره باز کنید:

nano .env

متغیر SECRET_ADMIN_URL را اضافه کنید:

testsite/.env
DJANGO_SETTINGS_MODULE="testsite.settings.development"
SECRET_KEY="your_secret_key"
SECRET_ADMIN_URL="very_secret_url"

فایل را ذخیره و ببندید.

حالا Django را برای پنهان کردن URL ادمین با SECRET_ADMIN_URL تنظیم کنید:

nano testsite/urls.py

توجه: very_secret_url را با URL امن خود جایگزین کنید.

اگر رشته‌های تصادفی می‌خواهید، کتابخانه secrets.py پایتون عالی است برای تولید آن‌ها. مثال‌های‌شان برای برنامه‌های کوچک امن عالی هستند.

URL ادمین را ویرایش کنید:

testsite/testsite/urls.py
from django.contrib import admin
from django.urls import path
import environ

env = environ.Env()
environ.Env.read_env()

urlpatterns = [
    path(env('SECRET_ADMIN_URL') + '/admin/', admin.site.urls),
]

فایل را ذخیره و ببندید.

حالا صفحه لاگین ادمین در /very_secret_url/admin/ است نه /admin/:

[تصویر صفحه لاگین ادمین]

جمع بندی

در این راهنما، پروژه Django خود را برای استفاده آسان و امن در محیط‌های مختلف پیکربندی کردید. با تقسیم تنظیمات به فایل‌های مجزا برای توسعه و تولید، استفاده از .env برای مخفی کردن اطلاعات حساس مثل SECRET_KEY و URL ادمین، و فعال‌سازی ویژگی‌های امنیتی داخلی Django مانند HTTPS، حفاظت در برابر XSS و CSRF، پروژه‌ای امن و آماده برای استقرار ساختید. این رویکرد نه تنها امنیت پروژه را تقویت می‌کند، بلکه امکان جابه‌جایی سریع بین محیط‌ها را بدون کاهش بهره‌وری فراهم می‌آورد. برای اطلاعات بیشتر، مستندات Django و راهنماهای مرتبط را بررسی کنید.

به اشتراک بگذارید

برچسب‌ها: