Использование Django CSRF-защиты при просмотре изображений, хранящихся в Varnish
У меня есть представление Django с формой, использующей защиту CSRF. Я хочу, чтобы этот вид был кэширован Varnish, когда есть обычный запрос GET (поскольку все пользователи нуждаются в одной и той же форме, без входа в систему).
Итак, есть две проблемы:
-
Как кэшировать эту страницу в лаке, а не передавать кэшированные/старые версии скрытого поля csrf пользователю? Возможно ли кэшировать страницы с полем CSRF?
-
Мой лак по умолчанию удаляет все файлы cookie, как я могу легко удалить все файлы cookie, кроме файла cookie csrftoken? И мне нужно установить конкретный CSRF_COOKIE_DOMAIN?
Ответы
Ответ 1
Использование CSRF в представлении по существу означает, что каждый рендер представления по-разному отличается (хотя меняется только значение одного скрытого поля). Кэширование не работает в таком сценарии.
Тем не менее, Django предоставляет механизмы для обойти это ограничение, а именно файлы cookie, как вы, кажется, уже догадались. Итак, на вашей второй части есть две вещи, которые нужно сделать:
Вам нужно только установить CSRF_COOKIE_DOMAIN
в Django, если запрос будет поступать из другого домена, чем там, где он обрабатывается.
Ответ 2
Это на пару лет поздно, но вот как я недавно столкнулся с этой проблемой.
Трюк заключается в использовании ESI, который поддерживает лак. Мы берем фрагмент CSRF и вставляем его на свою страницу, в том числе через ESI при прохождении через лак, а также напрямую (например, при запуске локального сервера-разработчика).
csrf_esi.html:
{% csrf_token %}
csrf_token.html
{% if request.META.HTTP_X_VARNISH_USE_CACHE %}
<esi:include src="{% url 'esi_csrf_token' %}" />
{% else %}
{% include "csrf_esi.html" %}
{% endif %}
urls.py
from django.conf.urls import url
from django.views.generic import TemplateView
urlpatterns = [
...
url(r'csrf_esi.html', TemplateView.as_view(template_name="csrf_esi.html"), name='esi_csrf_token'),
]
csrf_esi.py
from django import template
register = template.Library()
@register.inclusion_tag('csrf_token.html', takes_context=True)
def csrf_token_esi(context):
return context
settings.py
TEMPLATES = [
{
...
'OPTIONS': {
...
'builtins': [
'path.to.csrf_esi',
],
}
}
]
Конфигурация Varnish
set req.http.X-Varnish-Use-Cache = true;
Вам также нужно присваивать белый цвет странице csrf_esi.html
, чтобы она никогда не кэшировалась и не добавляла set beresp.do_esi = true;
внутри функции vcl_fetch
. Я бы уточнил об этом, но я не установил эту часть системы и не понял на 100% себя.
Теперь вы можете просто использовать его, как обычный тэг {% csrf_token %}
:
<form action="">
{% csrf_token_esi %}
<button type="submit">Push me</button>
</form>
Немного настроить, но как только вы это сделаете, вам больше не придется смотреть на него.
Ответ 3
У меня были похожие проблемы с использованием @csrf_protect и AJX, если кто-то использует этот декоратор, это может помочь
Также добавление исключений для лака. Убедитесь, что и представление с формой и представлением, которое данные отправляют, чтобы использовать декоратор.
У меня был только @csrf_protect в представлении post, который работал тонким тестированием локально, но когда я вышел в эфир o получил ошибку проверки 403, добавив, что декоратор полностью просмотрел эту страницу,