Проверка CSRF не удалась. Запрос прерван. Проверка происхождения не удалась
Вот моя установка:
localhost (Windows 11)
- Nginx
listening on port 80 and 443, 80 is NOT automatically redirected to 443
each proxy_passed to http://wsgi-server where wsgi-server=127.0.0.1:8080
- waitress_wsgi running as a service on port 8080
Вот конфигурация Django:
<!-- email_test.html -->
<!-- ... -->
<form action="{% url 'identity:email_test' %}" method="post">
{% csrf_token %}
{{ email_form }}
{% translate 'Send email' as submit_translated %}
<!-- I use django_bootstrap5 -->
{% bootstrap_button button_type="submit" content=submit_translated extra_classes='w-100'%}
</form>
# settings.py ----------
MIDDLEWARE = {
# ...
'django.middleware.csrf.CsrfViewMiddleware',
# ...
}
# forms.py -------------
class EmailTestForm(forms.Form):
email = forms.EmailField(
# help_text=password_validation.password_validators_help_text_html(),
label=_('Email'),
max_length=128,
)
# views.py -------------
def email_test(request):
context = {}
context.update(template_globals())
if request.method == "POST":
email_form = EmailTestForm(request.POST)
if email_form.is_valid():
email_obj = EmailMessage(subject='Hello', body='Email body',
from_email='noreply@nutrihub.hnet',
to=[email_form.cleaned_data.get('email')])
email_obj.send(fail_silently=False)
else:
email_form = EmailTestForm()
context['email_form'] = email_form
return render(request, "identity/email_test.html", context)
Вот мои тестовые результаты при посещении URL в браузере:
py manage.py runserver
(порт по умолчанию 8000), браузерhttp://127.0.0.1:8000
, пустойsettings.CSRF_TRUSTED_ORIGINS
: Работает нормально.- Браузер
http://localhost
илиhttp://127.0.0.1
илиhttps://localhost
илиhttps://127.0.0.1
с отдельной записью не вsettings.CSRF_TRUSTED_ORIGINS
: CSRF-ошибка. - Браузер
http://localhost
илиhttp://127.0.0.1
илиhttps://localhost
илиhttps://127.0.0.1
с отдельной записью неsettings.CSRF_TRUSTED_ORIGINS
: Работает нормально. - Браузер
https://mymachine.net
с этой записью вetc/hosts
разрешается в127.0.0.1
, а вsettings.CSRF_TRUSTED_ORIGINS
нет: CSRF error. - Браузер
https://mymachine.net
с этой записью вetc/hosts
, разрешающейся в127.0.0.1
и вsettings.CSRF_TRUSTED_ORIGINS
: Работает нормально. - Браузер
http://localhost:8080
илиhttp://localhost
илиhttp://mymachine.net:8080
: Работает нормально.
Значит ли это, что для (2-5), поскольку фактическим сервером, на котором работает приложение Django, является WSGI-сервер на порту 8080, запрос, переданный с веб-сервера, не считается тем же сайтом?
Мне удалось решить эту проблему. Благодаря этому решению мне не пришлось добавлять никаких записей в settings.CSRF_TRUSTED_ORIGINS
.
- Nginx config:
upstream wsgi-server {
server 127.0.0.1:8080;
}
server {
# ...
location / {
proxy_pass http://wsgi-server/;
# These resolved CSRF error
proxy_set_header X-Forwarded-Proto $scheme;
proxy_set_header X-Forwarded-Host $host;
proxy_set_header X-Forwarded-Port $server_port;
}
}
- Конфигурация WSGI Waitress (чтобы
X-Forwarded-*
проходил в Django):
# waitress_wsgi.py
serve(application,
trusted_proxy='proxy-ip',
trusted_proxy_headers=('x-forwarded-host', 'x-forwarded-proto',
'x-forwarded-port'))
После этого http
|https
, localhost
|127.0.0.1
|mymachine.net
, anyport, начали работать без ошибок.