Fix CSRF 403 error: add X-Forwarded-Host header to Nginx and update CSRF_TRUSTED_ORIGINS
- Created nginx-smartsoltech-fixed.conf with proper SSL and CSRF support - Preserved existing SSL certificates from /etc/letsencrypt/live/www.smartsoltech.kr/ - Added X-Forwarded-Host header (critical for Django CSRF validation) - Fixed location block order (static/media before /) - Implemented proper HTTP→HTTPS and www→non-www redirects - Updated CSRF_FIX.md with comprehensive troubleshooting guide
This commit is contained in:
563
CSRF_FIX.md
Normal file
563
CSRF_FIX.md
Normal file
@@ -0,0 +1,563 @@
|
|||||||
|
# 🔒 Исправление ошибки CSRF 403 в админке через Nginx
|
||||||
|
|
||||||
|
## ❌ Проблема
|
||||||
|
```
|
||||||
|
Ошибка доступа (403)
|
||||||
|
Ошибка проверки CSRF. Запрос отклонён.
|
||||||
|
```
|
||||||
|
|
||||||
|
Появляется при входе в админку через Nginx (https://smartsoltech.kr/admin/)
|
||||||
|
|
||||||
|
## 💡 Причина
|
||||||
|
|
||||||
|
Django проверяет источник запроса (origin) для защиты от CSRF атак. Когда запрос идёт через Nginx:
|
||||||
|
1. Django видит заголовок `Origin: https://smartsoltech.kr`
|
||||||
|
2. Но в `CSRF_TRUSTED_ORIGINS` нет этого домена
|
||||||
|
3. Nginx не передаёт заголовок `X-Forwarded-Host` (критично для CSRF)
|
||||||
|
4. Django отклоняет запрос как небезопасный
|
||||||
|
|
||||||
|
**Ваша конфигурация SSL:** Сертификаты находятся в `/etc/letsencrypt/live/www.smartsoltech.kr/`
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## ✅ Решение (2 простых шага)
|
||||||
|
|
||||||
|
### Шаг 1: Обновить Nginx конфигурацию
|
||||||
|
|
||||||
|
```bash
|
||||||
|
# На сервере
|
||||||
|
cd /opt/smartsoltech_site
|
||||||
|
git pull origin master
|
||||||
|
|
||||||
|
# Применить исправленную конфигурацию (сохраняет ваши SSL сертификаты)
|
||||||
|
sudo cp nginx-smartsoltech-fixed.conf /etc/nginx/sites-available/smartsoltech
|
||||||
|
|
||||||
|
# Проверить синтаксис
|
||||||
|
sudo nginx -t
|
||||||
|
|
||||||
|
# Если OK - перезагрузить Nginx
|
||||||
|
sudo systemctl reload nginx
|
||||||
|
```
|
||||||
|
|
||||||
|
**Что исправили в Nginx:**
|
||||||
|
- ✅ Добавлен `X-Forwarded-Host: $host` (критично для CSRF)
|
||||||
|
- ✅ Сохранены ваши SSL сертификаты из `/etc/letsencrypt/live/www.smartsoltech.kr/`
|
||||||
|
- ✅ Правильный порядок location блоков (/static/ перед /)
|
||||||
|
- ✅ Redirect www → non-www
|
||||||
|
- ✅ Redirect HTTP → HTTPS
|
||||||
|
|
||||||
|
### Шаг 2: Обновить CSRF_TRUSTED_ORIGINS в .env
|
||||||
|
|
||||||
|
```bash
|
||||||
|
# Редактировать .env
|
||||||
|
cd /opt/smartsoltech_site
|
||||||
|
nano .env
|
||||||
|
```
|
||||||
|
|
||||||
|
**НАЙТИ строку:**
|
||||||
|
```env
|
||||||
|
CSRF_TRUSTED_ORIGINS=http://localhost:8000,https://smartsoltech.kr
|
||||||
|
```
|
||||||
|
|
||||||
|
**ЗАМЕНИТЬ НА:**
|
||||||
|
```env
|
||||||
|
CSRF_TRUSTED_ORIGINS=http://localhost:8000,http://smartsoltech.kr,https://smartsoltech.kr,https://www.smartsoltech.kr
|
||||||
|
```
|
||||||
|
|
||||||
|
**Сохранить:** Ctrl+O, Enter, Ctrl+X
|
||||||
|
|
||||||
|
**Перезапустить Django:**
|
||||||
|
```bash
|
||||||
|
docker restart django_app
|
||||||
|
|
||||||
|
# Проверить что контейнер запущен
|
||||||
|
docker ps | grep django_app
|
||||||
|
```
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
### Вариант 2: Ручное исправление
|
||||||
|
|
||||||
|
#### Шаг 1: Исправить Nginx конфиг
|
||||||
|
|
||||||
|
```bash
|
||||||
|
sudo nano /etc/nginx/sites-available/smartsoltech
|
||||||
|
```
|
||||||
|
|
||||||
|
**Найти секцию location / и добавить заголовки:**
|
||||||
|
|
||||||
|
```nginx
|
||||||
|
location / {
|
||||||
|
proxy_pass http://localhost:8000;
|
||||||
|
proxy_set_header Host $host;
|
||||||
|
proxy_set_header X-Real-IP $remote_addr;
|
||||||
|
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
|
||||||
|
proxy_set_header X-Forwarded-Proto $scheme;
|
||||||
|
proxy_set_header X-Forwarded-Host $host; # ДОБАВИТЬ
|
||||||
|
proxy_set_header X-Forwarded-Port $server_port; # ДОБАВИТЬ
|
||||||
|
proxy_redirect off;
|
||||||
|
proxy_buffering off;
|
||||||
|
...
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
**Проверить и перезагрузить:**
|
||||||
|
```bash
|
||||||
|
sudo nginx -t
|
||||||
|
sudo systemctl reload nginx
|
||||||
|
```
|
||||||
|
|
||||||
|
#### Шаг 2: Исправить .env файл
|
||||||
|
|
||||||
|
```bash
|
||||||
|
cd /opt/smartsoltech_site
|
||||||
|
nano .env
|
||||||
|
```
|
||||||
|
|
||||||
|
**Найти строку:**
|
||||||
|
```env
|
||||||
|
CSRF_TRUSTED_ORIGINS=http://localhost:8000,https://smartsoltech.kr
|
||||||
|
```
|
||||||
|
|
||||||
|
**Заменить на:**
|
||||||
|
```env
|
||||||
|
CSRF_TRUSTED_ORIGINS=http://localhost:8000,http://smartsoltech.kr,https://smartsoltech.kr
|
||||||
|
```
|
||||||
|
|
||||||
|
**Сохранить:** Ctrl+O, Enter, Ctrl+X
|
||||||
|
|
||||||
|
#### Шаг 3: Перезапустить Django
|
||||||
|
|
||||||
|
```bash
|
||||||
|
docker compose restart django_app
|
||||||
|
|
||||||
|
# Проверить логи
|
||||||
|
docker logs django_app --tail 50
|
||||||
|
```
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## 🧪 Проверка работы
|
||||||
|
|
||||||
|
### Тест 1: Проверка переменных окружения
|
||||||
|
|
||||||
|
```bash
|
||||||
|
# Убедиться что Django видит правильный CSRF_TRUSTED_ORIGINS
|
||||||
|
docker exec django_app env | grep CSRF_TRUSTED_ORIGINS
|
||||||
|
|
||||||
|
# Должен вывести:
|
||||||
|
# CSRF_TRUSTED_ORIGINS=http://localhost:8000,http://smartsoltech.kr,https://smartsoltech.kr,https://www.smartsoltech.kr
|
||||||
|
```
|
||||||
|
|
||||||
|
### Тест 2: Проверка входа в админку
|
||||||
|
|
||||||
|
1. Открыть браузер: **https://smartsoltech.kr/admin/**
|
||||||
|
2. Ввести логин и пароль
|
||||||
|
3. Нажать "Войти"
|
||||||
|
4. ✅ **Должен успешно войти без ошибки 403**
|
||||||
|
|
||||||
|
### Тест 3: Проверка Nginx заголовков
|
||||||
|
|
||||||
|
```bash
|
||||||
|
# Проверить что Nginx передаёт все нужные заголовки
|
||||||
|
curl -v https://smartsoltech.kr/admin/ 2>&1 | grep -i forward
|
||||||
|
|
||||||
|
# Должны быть:
|
||||||
|
# X-Forwarded-Proto: https
|
||||||
|
# X-Forwarded-Host: smartsoltech.kr
|
||||||
|
```
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## 🔧 Если проблема осталась
|
||||||
|
|
||||||
|
### Диагностика 1: Проверить Django логи
|
||||||
|
|
||||||
|
```bash
|
||||||
|
# Смотреть логи в реальном времени
|
||||||
|
docker logs -f django_app
|
||||||
|
|
||||||
|
# Искать строки с CSRF:
|
||||||
|
# Forbidden (CSRF cookie not set.)
|
||||||
|
# Forbidden (CSRF token missing or incorrect)
|
||||||
|
# Origin checking failed - https://smartsoltech.kr does not match any trusted origins
|
||||||
|
```
|
||||||
|
|
||||||
|
### Диагностика 2: Проверить Nginx конфиг
|
||||||
|
|
||||||
|
```bash
|
||||||
|
# Проверить что изменения применились
|
||||||
|
sudo nginx -T | grep -A 10 "location /"
|
||||||
|
|
||||||
|
# Должны быть все proxy_set_header, особенно:
|
||||||
|
# proxy_set_header X-Forwarded-Host $host;
|
||||||
|
```
|
||||||
|
|
||||||
|
### Диагностика 3: Очистить кэш браузера
|
||||||
|
|
||||||
|
1. Открыть DevTools (F12)
|
||||||
|
2. Перейти в Network
|
||||||
|
3. Правый клик → "Clear browser cache"
|
||||||
|
4. Попробовать войти заново
|
||||||
|
|
||||||
|
### Диагностика 4: Временно включить DEBUG (ОСТОРОЖНО!)
|
||||||
|
|
||||||
|
```bash
|
||||||
|
# ТОЛЬКО ДЛЯ ДИАГНОСТИКИ! Выключить сразу после!
|
||||||
|
nano /opt/smartsoltech_site/.env
|
||||||
|
|
||||||
|
# Изменить
|
||||||
|
DEBUG=True
|
||||||
|
|
||||||
|
# Перезапустить
|
||||||
|
docker restart django_app
|
||||||
|
|
||||||
|
# Открыть админку - увидите детальную ошибку
|
||||||
|
|
||||||
|
# СРАЗУ ВЕРНУТЬ:
|
||||||
|
DEBUG=False
|
||||||
|
docker restart django_app
|
||||||
|
```
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## 📝 Объяснение что было исправлено
|
||||||
|
|
||||||
|
### Проблема в деталях:
|
||||||
|
|
||||||
|
1. **Браузер** → отправляет HTTPS запрос: `https://smartsoltech.kr/admin/login/`
|
||||||
|
2. **Nginx** → принимает HTTPS, проксирует к Django как HTTP: `http://localhost:8000`
|
||||||
|
3. **Django** → проверяет CSRF токен
|
||||||
|
4. **Django** → сравнивает Origin с CSRF_TRUSTED_ORIGINS
|
||||||
|
5. **❌ Ошибка:** В CSRF_TRUSTED_ORIGINS не было `https://smartsoltech.kr`
|
||||||
|
6. **❌ Ошибка:** Nginx не передавал `X-Forwarded-Host` → Django не знал реальный домен
|
||||||
|
7. **Результат:** Django отклонял запрос (403 Forbidden)
|
||||||
|
|
||||||
|
### Что исправили:
|
||||||
|
|
||||||
|
1. ✅ Добавили `https://smartsoltech.kr` в CSRF_TRUSTED_ORIGINS
|
||||||
|
2. ✅ Добавили `http://smartsoltech.kr` для HTTP→HTTPS redirect
|
||||||
|
3. ✅ Nginx передаёт `X-Forwarded-Proto: https`
|
||||||
|
4. ✅ Nginx передаёт `X-Forwarded-Host: smartsoltech.kr` (КРИТИЧНО!)
|
||||||
|
5. ✅ Django понимает что оригинальный запрос был HTTPS от smartsoltech.kr
|
||||||
|
6. ✅ CSRF проверка проходит успешно
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## 🔐 Правильная финальная конфигурация
|
||||||
|
|
||||||
|
### 📄 .env (на сервере):
|
||||||
|
```env
|
||||||
|
DEBUG=False
|
||||||
|
ALLOWED_HOSTS=localhost,127.0.0.1,smartsoltech.kr,www.smartsoltech.kr,192.168.0.102
|
||||||
|
CSRF_TRUSTED_ORIGINS=http://localhost:8000,http://smartsoltech.kr,https://smartsoltech.kr,https://www.smartsoltech.kr
|
||||||
|
```
|
||||||
|
|
||||||
|
### 📄 Nginx /etc/nginx/sites-available/smartsoltech:
|
||||||
|
|
||||||
|
```nginx
|
||||||
|
upstream django_app {
|
||||||
|
server localhost:8000;
|
||||||
|
}
|
||||||
|
|
||||||
|
# HTTP → HTTPS redirect
|
||||||
|
server {
|
||||||
|
listen 80;
|
||||||
|
server_name smartsoltech.kr www.smartsoltech.kr;
|
||||||
|
return 301 https://$host$request_uri;
|
||||||
|
}
|
||||||
|
|
||||||
|
# www → non-www redirect
|
||||||
|
server {
|
||||||
|
listen 443 ssl http2;
|
||||||
|
server_name www.smartsoltech.kr;
|
||||||
|
|
||||||
|
ssl_certificate /etc/letsencrypt/live/www.smartsoltech.kr/fullchain.pem;
|
||||||
|
ssl_certificate_key /etc/letsencrypt/live/www.smartsoltech.kr/privkey.pem;
|
||||||
|
|
||||||
|
return 301 https://smartsoltech.kr$request_uri;
|
||||||
|
}
|
||||||
|
|
||||||
|
# Main HTTPS server
|
||||||
|
server {
|
||||||
|
listen 443 ssl http2;
|
||||||
|
server_name smartsoltech.kr;
|
||||||
|
|
||||||
|
# SSL certificates (ваши существующие сертификаты)
|
||||||
|
ssl_certificate /etc/letsencrypt/live/www.smartsoltech.kr/fullchain.pem;
|
||||||
|
ssl_certificate_key /etc/letsencrypt/live/www.smartsoltech.kr/privkey.pem;
|
||||||
|
include /etc/letsencrypt/options-ssl-nginx.conf;
|
||||||
|
ssl_dhparam /etc/letsencrypt/ssl-dhparams.pem;
|
||||||
|
|
||||||
|
# Security headers
|
||||||
|
add_header Strict-Transport-Security "max-age=31536000; includeSubDomains" always;
|
||||||
|
add_header X-Content-Type-Options "nosniff" always;
|
||||||
|
add_header X-Frame-Options "SAMEORIGIN" always;
|
||||||
|
|
||||||
|
# Static files (ПЕРЕД location /)
|
||||||
|
location /static/ {
|
||||||
|
alias /opt/smartsoltech_site/smartsoltech/staticfiles/;
|
||||||
|
expires 30d;
|
||||||
|
add_header Cache-Control "public, immutable";
|
||||||
|
}
|
||||||
|
|
||||||
|
location /media/ {
|
||||||
|
alias /opt/smartsoltech_site/smartsoltech/media/;
|
||||||
|
expires 7d;
|
||||||
|
}
|
||||||
|
|
||||||
|
# Django proxy (с CSRF заголовками)
|
||||||
|
location / {
|
||||||
|
proxy_pass http://django_app;
|
||||||
|
|
||||||
|
# КРИТИЧНО для CSRF:
|
||||||
|
proxy_set_header Host $host;
|
||||||
|
proxy_set_header X-Real-IP $remote_addr;
|
||||||
|
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
|
||||||
|
proxy_set_header X-Forwarded-Proto $scheme;
|
||||||
|
proxy_set_header X-Forwarded-Host $host; # ← ВАЖНО!
|
||||||
|
|
||||||
|
proxy_redirect off;
|
||||||
|
proxy_buffering off;
|
||||||
|
proxy_read_timeout 60s;
|
||||||
|
proxy_connect_timeout 60s;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## ⚡ Быстрое решение одной командой
|
||||||
|
|
||||||
|
```bash
|
||||||
|
# НА СЕРВЕРЕ (выполнить всё за раз):
|
||||||
|
cd /opt/smartsoltech_site && \
|
||||||
|
git pull origin master && \
|
||||||
|
sudo cp nginx-smartsoltech-fixed.conf /etc/nginx/sites-available/smartsoltech && \
|
||||||
|
sudo nginx -t && sudo systemctl reload nginx && \
|
||||||
|
sed -i 's|CSRF_TRUSTED_ORIGINS=.*|CSRF_TRUSTED_ORIGINS=http://localhost:8000,http://smartsoltech.kr,https://smartsoltech.kr,https://www.smartsoltech.kr|' .env && \
|
||||||
|
docker restart django_app && \
|
||||||
|
sleep 3 && \
|
||||||
|
echo "✅ CSRF исправлен! Проверьте: https://smartsoltech.kr/admin/" && \
|
||||||
|
docker ps | grep django_app
|
||||||
|
```
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## ✅ Финальный чеклист
|
||||||
|
|
||||||
|
- [ ] Git pull выполнен (получен nginx-smartsoltech-fixed.conf)
|
||||||
|
- [ ] Nginx конфиг скопирован в /etc/nginx/sites-available/smartsoltech
|
||||||
|
- [ ] `sudo nginx -t` успешно (OK)
|
||||||
|
- [ ] `sudo systemctl reload nginx` выполнен
|
||||||
|
- [ ] CSRF_TRUSTED_ORIGINS обновлён в .env (добавлены http:// и https:// версии)
|
||||||
|
- [ ] `docker restart django_app` выполнен
|
||||||
|
- [ ] Контейнер django_app запущен (docker ps)
|
||||||
|
- [ ] **Вход в админку работает без ошибки 403** ✅
|
||||||
|
- [ ] DEBUG=False в .env (безопасность)
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## 📞 Если нужна помощь
|
||||||
|
|
||||||
|
Если после всех шагов проблема осталась, отправьте:
|
||||||
|
|
||||||
|
```bash
|
||||||
|
# 1. Django логи
|
||||||
|
docker logs django_app --tail 100
|
||||||
|
|
||||||
|
# 2. Nginx конфиг
|
||||||
|
sudo nginx -T | grep -A 30 "server_name smartsoltech.kr"
|
||||||
|
|
||||||
|
# 3. Переменные окружения Django
|
||||||
|
docker exec django_app env | grep -E "(CSRF|ALLOWED|DEBUG)"
|
||||||
|
|
||||||
|
# 4. Тест curl
|
||||||
|
curl -v https://smartsoltech.kr/admin/ 2>&1 | head -50
|
||||||
|
```
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
**Создано:** 24 ноября 2025 г.
|
||||||
|
**Проблема:** CSRF 403 ошибка при входе в админку через Nginx + SSL
|
||||||
|
**Решение:** Добавить домен в CSRF_TRUSTED_ORIGINS + исправить Nginx заголовки (X-Forwarded-Host)
|
||||||
|
**Статус:** ✅ Готово к применению
|
||||||
|
|
||||||
|
|
||||||
|
# НЕ должно быть:
|
||||||
|
# HTTP/1.1 403 Forbidden
|
||||||
|
```
|
||||||
|
|
||||||
|
### Проверка 2: Через браузер
|
||||||
|
|
||||||
|
1. Открыть http://smartsoltech.kr/admin/
|
||||||
|
2. Ввести логин и пароль
|
||||||
|
3. Нажать "Войти"
|
||||||
|
4. ✅ Должно успешно войти в админку
|
||||||
|
5. ❌ НЕ должно показывать ошибку CSRF 403
|
||||||
|
|
||||||
|
### Проверка 3: Логи Django
|
||||||
|
|
||||||
|
```bash
|
||||||
|
docker logs django_app --tail 20 | grep -i csrf
|
||||||
|
|
||||||
|
# НЕ должно быть:
|
||||||
|
# "CSRF verification failed"
|
||||||
|
# "Forbidden (CSRF token missing or incorrect)"
|
||||||
|
```
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## 📝 Понимание настроек CSRF
|
||||||
|
|
||||||
|
### CSRF_TRUSTED_ORIGINS - что это?
|
||||||
|
|
||||||
|
Django сравнивает HTTP заголовок `Origin` с этим списком:
|
||||||
|
|
||||||
|
```python
|
||||||
|
# В Django settings.py читается из .env:
|
||||||
|
CSRF_TRUSTED_ORIGINS = [
|
||||||
|
'http://localhost:8000', # Для локальной разработки
|
||||||
|
'http://smartsoltech.kr', # Для HTTP запросов (до получения SSL)
|
||||||
|
'https://smartsoltech.kr', # Для HTTPS запросов (после SSL)
|
||||||
|
]
|
||||||
|
```
|
||||||
|
|
||||||
|
### Когда нужен каждый origin:
|
||||||
|
|
||||||
|
| Origin | Когда используется |
|
||||||
|
|--------|-------------------|
|
||||||
|
| `http://localhost:8000` | Django напрямую (без Nginx) |
|
||||||
|
| `http://smartsoltech.kr` | Через Nginx БЕЗ SSL |
|
||||||
|
| `https://smartsoltech.kr` | Через Nginx С SSL |
|
||||||
|
|
||||||
|
### После получения SSL сертификата:
|
||||||
|
|
||||||
|
```env
|
||||||
|
# Можно убрать HTTP, оставить только HTTPS:
|
||||||
|
CSRF_TRUSTED_ORIGINS=http://localhost:8000,https://smartsoltech.kr,https://www.smartsoltech.kr
|
||||||
|
```
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## 🔧 Дополнительные проверки
|
||||||
|
|
||||||
|
### Если ошибка всё ещё есть:
|
||||||
|
|
||||||
|
#### 1. Проверить что Django видит правильные заголовки
|
||||||
|
|
||||||
|
```bash
|
||||||
|
# Включить DEBUG=True временно
|
||||||
|
nano /opt/smartsoltech_site/.env
|
||||||
|
# DEBUG=True
|
||||||
|
|
||||||
|
docker compose restart django_app
|
||||||
|
|
||||||
|
# Открыть http://smartsoltech.kr/admin/ в браузере
|
||||||
|
# Django покажет детальную информацию об ошибке
|
||||||
|
```
|
||||||
|
|
||||||
|
#### 2. Проверить ALLOWED_HOSTS
|
||||||
|
|
||||||
|
```bash
|
||||||
|
# В .env должно быть:
|
||||||
|
ALLOWED_HOSTS=localhost,127.0.0.1,smartsoltech.kr,www.smartsoltech.kr
|
||||||
|
```
|
||||||
|
|
||||||
|
#### 3. Проверить что Nginx передаёт правильный Host
|
||||||
|
|
||||||
|
```bash
|
||||||
|
# В логах Django должен быть правильный host
|
||||||
|
docker logs django_app --tail 50 | grep "GET /admin"
|
||||||
|
|
||||||
|
# Должно показывать:
|
||||||
|
# [INFO] "GET /admin/ HTTP/1.1" 200
|
||||||
|
# Host: smartsoltech.kr
|
||||||
|
```
|
||||||
|
|
||||||
|
#### 4. Тест с curl
|
||||||
|
|
||||||
|
```bash
|
||||||
|
# Симуляция браузера с Origin заголовком
|
||||||
|
curl -H "Origin: http://smartsoltech.kr" \
|
||||||
|
-H "Referer: http://smartsoltech.kr/admin/" \
|
||||||
|
-I http://smartsoltech.kr/admin/login/
|
||||||
|
|
||||||
|
# Должно вернуть 200 или 302, НЕ 403
|
||||||
|
```
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## ⚠️ Важные замечания
|
||||||
|
|
||||||
|
### Безопасность
|
||||||
|
|
||||||
|
1. **DEBUG=False в продакшене** - всегда!
|
||||||
|
```env
|
||||||
|
DEBUG=False # ✅ В продакшене
|
||||||
|
DEBUG=True # ❌ Только для отладки локально
|
||||||
|
```
|
||||||
|
|
||||||
|
2. **HTTPS рекомендуется** - после получения SSL:
|
||||||
|
```nginx
|
||||||
|
# Редирект всех HTTP на HTTPS
|
||||||
|
server {
|
||||||
|
listen 80;
|
||||||
|
return 301 https://$host$request_uri;
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
3. **www.smartsoltech.kr** - если используется:
|
||||||
|
```env
|
||||||
|
ALLOWED_HOSTS=localhost,127.0.0.1,smartsoltech.kr,www.smartsoltech.kr
|
||||||
|
CSRF_TRUSTED_ORIGINS=http://smartsoltech.kr,http://www.smartsoltech.kr,https://smartsoltech.kr,https://www.smartsoltech.kr
|
||||||
|
```
|
||||||
|
|
||||||
|
### После получения SSL
|
||||||
|
|
||||||
|
1. Обновить Nginx конфиг (раскомментировать SSL строки)
|
||||||
|
2. Обновить .env:
|
||||||
|
```env
|
||||||
|
# Можно убрать HTTP origins (оставить только для localhost)
|
||||||
|
CSRF_TRUSTED_ORIGINS=http://localhost:8000,https://smartsoltech.kr,https://www.smartsoltech.kr
|
||||||
|
```
|
||||||
|
3. Перезапустить:
|
||||||
|
```bash
|
||||||
|
sudo systemctl reload nginx
|
||||||
|
docker compose restart django_app
|
||||||
|
```
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## 🎯 Быстрое решение (одной командой)
|
||||||
|
|
||||||
|
```bash
|
||||||
|
# На сервере выполнить всё сразу:
|
||||||
|
cd /opt/smartsoltech_site && \
|
||||||
|
git pull origin master && \
|
||||||
|
sudo cp nginx-smartsoltech.conf /etc/nginx/sites-available/smartsoltech && \
|
||||||
|
sudo nginx -t && \
|
||||||
|
sudo systemctl reload nginx && \
|
||||||
|
sed -i 's|CSRF_TRUSTED_ORIGINS=.*|CSRF_TRUSTED_ORIGINS=http://localhost:8000,http://smartsoltech.kr,https://smartsoltech.kr|' .env && \
|
||||||
|
docker compose restart django_app && \
|
||||||
|
echo "✅ CSRF исправлен! Проверьте: http://smartsoltech.kr/admin/"
|
||||||
|
```
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## 📊 Чеклист исправления
|
||||||
|
|
||||||
|
- [ ] Nginx конфиг обновлён (добавлены X-Forwarded-Host и X-Forwarded-Port)
|
||||||
|
- [ ] `sudo nginx -t` успешно
|
||||||
|
- [ ] `sudo systemctl reload nginx` выполнен
|
||||||
|
- [ ] `.env` обновлён (добавлен http://smartsoltech.kr в CSRF_TRUSTED_ORIGINS)
|
||||||
|
- [ ] Django перезапущен (`docker compose restart django_app`)
|
||||||
|
- [ ] Админка открывается без ошибки 403
|
||||||
|
- [ ] Вход в админку работает
|
||||||
|
- [ ] Логи Django без ошибок CSRF
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
**Создано:** 24 ноября 2025 г.
|
||||||
|
**Проблема:** CSRF 403 при входе в админку через Nginx
|
||||||
|
**Решение:** Добавить X-Forwarded заголовки в Nginx + добавить http://smartsoltech.kr в CSRF_TRUSTED_ORIGINS
|
||||||
108
nginx-smartsoltech-fixed.conf
Normal file
108
nginx-smartsoltech-fixed.conf
Normal file
@@ -0,0 +1,108 @@
|
|||||||
|
# SmartSolTech Nginx Configuration
|
||||||
|
# Исправленная версия с SSL сертификатами и CSRF headers
|
||||||
|
|
||||||
|
upstream django_app {
|
||||||
|
server localhost:8000;
|
||||||
|
}
|
||||||
|
|
||||||
|
# HTTP → HTTPS редирект
|
||||||
|
server {
|
||||||
|
listen 80;
|
||||||
|
listen [::]:80;
|
||||||
|
server_name smartsoltech.kr www.smartsoltech.kr;
|
||||||
|
|
||||||
|
# Let's Encrypt challenge
|
||||||
|
location /.well-known/acme-challenge/ {
|
||||||
|
root /var/www/certbot;
|
||||||
|
}
|
||||||
|
|
||||||
|
location / {
|
||||||
|
return 301 https://$host$request_uri;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
# Редирект с www на non-www (HTTPS)
|
||||||
|
server {
|
||||||
|
listen 443 ssl http2;
|
||||||
|
listen [::]:443 ssl http2;
|
||||||
|
server_name www.smartsoltech.kr;
|
||||||
|
|
||||||
|
# SSL сертификаты
|
||||||
|
ssl_certificate /etc/letsencrypt/live/www.smartsoltech.kr/fullchain.pem;
|
||||||
|
ssl_certificate_key /etc/letsencrypt/live/www.smartsoltech.kr/privkey.pem;
|
||||||
|
include /etc/letsencrypt/options-ssl-nginx.conf;
|
||||||
|
ssl_dhparam /etc/letsencrypt/ssl-dhparams.pem;
|
||||||
|
|
||||||
|
return 301 https://smartsoltech.kr$request_uri;
|
||||||
|
}
|
||||||
|
|
||||||
|
# Основной HTTPS сервер
|
||||||
|
server {
|
||||||
|
listen 443 ssl http2;
|
||||||
|
listen [::]:443 ssl http2;
|
||||||
|
server_name smartsoltech.kr;
|
||||||
|
|
||||||
|
# SSL сертификаты
|
||||||
|
ssl_certificate /etc/letsencrypt/live/www.smartsoltech.kr/fullchain.pem;
|
||||||
|
ssl_certificate_key /etc/letsencrypt/live/www.smartsoltech.kr/privkey.pem;
|
||||||
|
include /etc/letsencrypt/options-ssl-nginx.conf;
|
||||||
|
ssl_dhparam /etc/letsencrypt/ssl-dhparams.pem;
|
||||||
|
|
||||||
|
# Максимальный размер загружаемых файлов
|
||||||
|
client_max_body_size 100M;
|
||||||
|
|
||||||
|
# Security headers
|
||||||
|
add_header Strict-Transport-Security "max-age=31536000; includeSubDomains" always;
|
||||||
|
add_header X-Frame-Options "SAMEORIGIN" always;
|
||||||
|
add_header X-Content-Type-Options "nosniff" always;
|
||||||
|
add_header X-XSS-Protection "1; mode=block" always;
|
||||||
|
|
||||||
|
# Логи
|
||||||
|
access_log /var/log/nginx/smartsoltech_access.log;
|
||||||
|
error_log /var/log/nginx/smartsoltech_error.log;
|
||||||
|
|
||||||
|
# Статические файлы - ВАЖНО: должны быть ПЕРЕД location /
|
||||||
|
location /static/ {
|
||||||
|
alias /opt/smartsoltech_site/smartsoltech/staticfiles/;
|
||||||
|
expires 30d;
|
||||||
|
add_header Cache-Control "public, immutable";
|
||||||
|
access_log off;
|
||||||
|
}
|
||||||
|
|
||||||
|
# Медиа файлы
|
||||||
|
location /media/ {
|
||||||
|
alias /opt/smartsoltech_site/smartsoltech/media/;
|
||||||
|
expires 7d;
|
||||||
|
add_header Cache-Control "public";
|
||||||
|
access_log off;
|
||||||
|
}
|
||||||
|
|
||||||
|
# Прокси к Django приложению
|
||||||
|
location / {
|
||||||
|
proxy_pass http://django_app;
|
||||||
|
|
||||||
|
# Заголовки для Django
|
||||||
|
proxy_set_header Host $host;
|
||||||
|
proxy_set_header X-Real-IP $remote_addr;
|
||||||
|
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
|
||||||
|
proxy_set_header X-Forwarded-Proto $scheme;
|
||||||
|
|
||||||
|
# ВАЖНО для CSRF: Django должен знать оригинальный протокол
|
||||||
|
proxy_set_header X-Forwarded-Host $host;
|
||||||
|
|
||||||
|
proxy_redirect off;
|
||||||
|
proxy_buffering off;
|
||||||
|
|
||||||
|
# Таймауты
|
||||||
|
proxy_connect_timeout 60s;
|
||||||
|
proxy_send_timeout 60s;
|
||||||
|
proxy_read_timeout 60s;
|
||||||
|
}
|
||||||
|
|
||||||
|
# Deny access to sensitive files
|
||||||
|
location ~ /\. {
|
||||||
|
deny all;
|
||||||
|
access_log off;
|
||||||
|
log_not_found off;
|
||||||
|
}
|
||||||
|
}
|
||||||
Reference in New Issue
Block a user