Security: fix middleware order and CSRF protection
This commit is contained in:
@@ -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',
|
||||
]
|
||||
# Улучшенный блок INTERNAL_IPS (для Docker и локальной разработки)
|
||||
if DEBUG_TOOLBAR_ENABLED:
|
||||
import socket
|
||||
INTERNAL_IPS = ['127.0.0.1', '10.0.2.2', 'localhost']
|
||||
|
||||
# Если запускаете в Docker, добавьте IP хоста
|
||||
# Например: INTERNAL_IPS += ['172.17.0.1', '192.168.65.1'] # Docker Desktop
|
||||
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,
|
||||
}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user