Security: fix middleware order and CSRF protection

This commit is contained in:
2026-01-07 23:14:51 +03:00
parent f5130a79fd
commit b7fffb55bf

View File

@@ -18,7 +18,7 @@ BASE_DIR = Path(__file__).resolve().parent.parent
# Initialize environment variables
env = environ.Env(
# Set casting and default values
DEBUG=(bool, True),
DEBUG=(bool, False), # Security: default False
SECRET_KEY=(str, 'django-insecure-default-key-change-in-production'),
)
@@ -36,16 +36,19 @@ if env_file.exists():
SECRET_KEY = env('SECRET_KEY')
# SECURITY WARNING: don't run with debug turned on in production!
DEBUG = env('DEBUG')
DEBUG = env.bool('DEBUG', False)
DEBUG_TOOLBAR_ENABLED = DEBUG and env.bool('DEBUG_TOOLBAR_ENABLED', False)
# Allowed hosts: читаем из переменной окружения или используем wildcard для разработки
# Allowed hosts: читаем из переменной окружения
# В .env на проде: ALLOWED_HOSTS=mix.smaa.by,*.mix.smaa.by
ALLOWED_HOSTS = env.list('ALLOWED_HOSTS', default=['*'])
# CSRF trusted origins для работы за nginx proxy
# CSRF configuration
CSRF_TRUSTED_ORIGINS = env.list('CSRF_TRUSTED_ORIGINS', default=[
'https://mix.smaa.by',
'https://*.mix.smaa.by',
])
CSRF_USE_SESSIONS = True # Рекомендуется для мультихостовых систем
# ============================================
@@ -93,8 +96,8 @@ TENANT_APPS = [
# Объединяем для INSTALLED_APPS
INSTALLED_APPS = list(SHARED_APPS) + [app for app in TENANT_APPS if app not in SHARED_APPS]
# Django Debug Toolbar (только в DEBUG режиме)
if DEBUG:
# Django Debug Toolbar
if DEBUG_TOOLBAR_ENABLED:
INSTALLED_APPS += ['debug_toolbar']
# Модели тенанта и домена
@@ -110,22 +113,21 @@ SHOW_PUBLIC_IF_NO_TENANT_FOUND = True
# ============================================
MIDDLEWARE = [
'whitenoise.middleware.WhiteNoiseMiddleware', # Static files first (no DB access needed)
'django_tenants.middleware.main.TenantMainMiddleware', # ОБЯЗАТЕЛЬНО ПЕРВЫМ!
'myproject.admin_access_middleware.TenantAdminAccessMiddleware', # SECURITY: Ограничение доступа к админке
'django.middleware.security.SecurityMiddleware',
'django_tenants.middleware.main.TenantMainMiddleware', # 1. Обязательно первым!
'django.middleware.security.SecurityMiddleware', # 2. Безопасность (HTTPS и заголовки)
'whitenoise.middleware.WhiteNoiseMiddleware', # 3. Статика (после безопасности)
'django.contrib.sessions.middleware.SessionMiddleware',
'django.middleware.common.CommonMiddleware',
'django.middleware.csrf.CsrfViewMiddleware',
'django.contrib.auth.middleware.AuthenticationMiddleware',
'django.contrib.auth.middleware.AuthenticationMiddleware', # 4. Определение пользователя
'myproject.admin_access_middleware.TenantAdminAccessMiddleware', # 5. ТЕПЕРЬ проверка работает (после auth)
'django.contrib.messages.middleware.MessageMiddleware',
'django.middleware.clickjacking.XFrameOptionsMiddleware',
'simple_history.middleware.HistoryRequestMiddleware', # История изменений
'simple_history.middleware.HistoryRequestMiddleware',
]
# Django Debug Toolbar Middleware (только в DEBUG режиме)
# ВАЖНО: добавляем ПОСЛЕ TenantMainMiddleware, чтобы toolbar видел корректный tenant
if DEBUG:
# Django Debug Toolbar Middleware
if DEBUG_TOOLBAR_ENABLED:
MIDDLEWARE.append('debug_toolbar.middleware.DebugToolbarMiddleware')
@@ -433,23 +435,36 @@ USE_HTTPS = env.bool('USE_HTTPS', default=False)
# DJANGO DEBUG TOOLBAR SETTINGS
# ============================================
if DEBUG:
# IP адреса, с которых разрешен доступ к Debug Toolbar
INTERNAL_IPS = [
'127.0.0.1',
'localhost',
]
# Если запускаете в Docker, добавьте IP хоста
# Например: INTERNAL_IPS += ['172.17.0.1', '192.168.65.1'] # Docker Desktop
# Улучшенный блок INTERNAL_IPS (для Docker и локальной разработки)
if DEBUG_TOOLBAR_ENABLED:
import socket
INTERNAL_IPS = ['127.0.0.1', '10.0.2.2', 'localhost']
try:
# Получаем все IP хоста (контейнера)
hostname, _, ips = socket.gethostbyname_ex(socket.gethostname())
for ip_str in ips:
try:
# Для IPv4: заменяем последний октет на 1 (шлюз Docker)
if '.' in ip_str:
parts = ip_str.split('.')
if len(parts) == 4:
gateway_ip = '.'.join(parts[:3] + ['1'])
INTERNAL_IPS.append(gateway_ip)
# Возможные шлюзы и алиасы
INTERNAL_IPS.extend([
'.'.join(parts[:3] + ['254']),
'host.docker.internal',
])
except (ValueError, AttributeError):
continue
except Exception as e:
print(f"Debug Info: Could not determine Docker gateway IPs: {e}")
# Конфигурация Debug Toolbar
DEBUG_TOOLBAR_CONFIG = {
# Показывать toolbar всегда при DEBUG=True и INTERNAL_IPS
'SHOW_TOOLBAR_CALLBACK': lambda request: DEBUG,
# Или можно фильтровать по tenant (например, только для определенных поддоменов):
# 'SHOW_TOOLBAR_CALLBACK': lambda request: DEBUG and getattr(request, 'tenant', None) and request.tenant.schema_name != 'public',
# Отключить для тестов
'SHOW_TOOLBAR_CALLBACK': lambda request: DEBUG_TOOLBAR_ENABLED,
'IS_RUNNING_TESTS': False,
}