Django - 安全性實踐
安全性是 Web 開發中最重要的方面之一。本節將探討如何在 Django 應用中實現安全性最佳實踐,保護應用免受常見攻擊。
課程目標
- 瞭解 Django 的內建安全功能。
- 學習如何防範常見的 Web 攻擊(如 XSS、CSRF、SQL 注入)。
- 配置安全的 Django 生產環境。
- 使用外部工具增強安全性。
課程內容
1. Django 內建安全功能
步驟 1:CSRF 保護
Django 默認啟用 CSRF 保護,防止跨站請求偽造。
在模板中使用 CSRF 標記:
1
2
3
4
5
<form method="post">
{% csrf_token %}
<input type="text" name="data" />
<button type="submit">Submit</button>
</form>
如果需要在非模板中發送 POST 請求(如 Ajax),請添加 CSRF 標記到請求頭:
1
2
3
4
5
6
7
fetch("/api/", {
method: "POST",
headers: {
"X-CSRFToken": getCookie("csrftoken"),
},
body: JSON.stringify({ data: "value" }),
});
步驟 2:XSS 保護
Django 模板自動對變數進行 HTML 轉義,防止跨站腳本攻擊(XSS)。
範例:
1
<p>{{ user_input }}</p>
若需顯示未轉義的 HTML,請使用 safe
過濾器(需謹慎使用):
1
<p>{{ user_input|safe }}</p>
步驟 3:SQL 注入防護
Django ORM 自動使用參數化查詢,防止 SQL 注入。
範例:
1
2
3
4
5
# 安全的查詢方式
User.objects.filter(username="example")
# 危險的查詢方式(避免使用)
cursor.execute(f"SELECT * FROM auth_user WHERE username = '{username}'")
步驟 4:密碼管理
Django 使用 PBKDF2 演算法對密碼進行哈希。
範例:
1
2
3
4
from django.contrib.auth.hashers import make_password, check_password
hashed_password = make_password('my_password')
is_valid = check_password('my_password', hashed_password)
可修改哈希演算法:
1
2
3
4
5
6
PASSWORD_HASHERS = [
'django.contrib.auth.hashers.Argon2PasswordHasher',
'django.contrib.auth.hashers.PBKDF2PasswordHasher',
'django.contrib.auth.hashers.PBKDF2SHA1PasswordHasher',
'django.contrib.auth.hashers.BCryptSHA256PasswordHasher',
]
2. 防禦常見攻擊
步驟 1:避免敏感數據暴露
確保以下敏感信息不出現在代碼庫中:
SECRET_KEY
- 資料庫憑證
- 第三方 API 密鑰
將它們存儲在環境變數或 .env
文件中:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
import os
from dotenv import load_dotenv
load_dotenv()
SECRET_KEY = os.getenv('DJANGO_SECRET_KEY')
DATABASES = {
'default': {
'ENGINE': 'django.db.backends.postgresql',
'NAME': os.getenv('DB_NAME'),
'USER': os.getenv('DB_USER'),
'PASSWORD': os.getenv('DB_PASSWORD'),
'HOST': os.getenv('DB_HOST'),
'PORT': os.getenv('DB_PORT'),
}
}
步驟 2:HTTPS 與 HSTS
- 在生產環境中,強制使用 HTTPS,確保數據加密傳輸。
- 啟用 HTTP 嚴格傳輸安全(HSTS):
在settings.py
中設置:
1
2
3
4
SECURE_SSL_REDIRECT = True
SECURE_HSTS_SECONDS = 31536000
SECURE_HSTS_INCLUDE_SUBDOMAINS = True
SECURE_HSTS_PRELOAD = True
步驟 3:內容安全策略(CSP)
使用 Django-CSP 強制限制加載的資源來源:
1
pip install django-csp
在 settings.py
中添加:
1
2
3
4
5
INSTALLED_APPS += ['csp']
CSP_DEFAULT_SRC = ["'self'"]
CSP_SCRIPT_SRC = ["'self'", "cdnjs.cloudflare.com"]
CSP_STYLE_SRC = ["'self'", "fonts.googleapis.com"]
CSP_FONT_SRC = ["fonts.gstatic.com"]
步驟 4:限制登入嘗試
防止暴力破解攻擊:
1
pip install django-axes
在 settings.py
中:
1
2
3
4
INSTALLED_APPS += ['axes']
MIDDLEWARE += ['axes.middleware.AxesMiddleware']
AXES_FAILURE_LIMIT = 5 # 最大嘗試次數
AXES_COOLOFF_TIME = 1 # 鎖定時間(小時)
3. 生產環境安全配置
步驟 1:關閉 DEBUG 模式
在生產環境中設置:
1
2
DEBUG = False
ALLOWED_HOSTS = ['yourdomain.com']
步驟 2:安全 Cookie 配置
1
2
3
4
SESSION_COOKIE_SECURE = True # 僅通過 HTTPS 傳輸
CSRF_COOKIE_SECURE = True # 僅通過 HTTPS 傳輸
SECURE_BROWSER_XSS_FILTER = True # 啟用瀏覽器的 XSS 過濾
SECURE_CONTENT_TYPE_NOSNIFF = True # 禁止 MIME 嗅探
步驟 3:屏蔽敏感信息
在錯誤頁面中隱藏敏感信息:
1
DEBUG_PROPAGATE_EXCEPTIONS = False
4. 安全工具
工具推薦
- OWASP ZAP:檢測應用漏洞。
- Sentry:錯誤跟蹤和安全事件記錄。
- django-secure:額外的安全性檢查。
Sentry 集成
1
pip install sentry-sdk
在 settings.py
中:
1
2
3
4
5
6
7
8
import sentry_sdk
from sentry_sdk.integrations.django import DjangoIntegration
sentry_sdk.init(
dsn="your_sentry_dsn",
integrations=[DjangoIntegration()],
send_default_pii=True,
)
課堂練習
- 改進 Day 7 的 Blog 應用:
- 為所有表單添加 CSRF 保護。
- 使用 CSP 限制資源來源。
- 限制登入失敗次數,防止暴力破解。
作業
- 為應用啟用 HTTPS 和 HSTS,並測試效果。
- 使用 OWASP ZAP 對應用進行掃描,修復檢測到的安全漏洞。
- 配置 Sentry,實時監控應用錯誤和安全事件。
本文章以 CC BY 4.0 授權