这已经晚了几年,但这是我最近解决这个问题的方法。
诀窍是使用清漆支持的ESI。我们获取 CSRF 片段并将其粘贴到自己的页面中,当通过 varnish 时通过 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 %}
网址.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
设置.py
TEMPLATES = [
{
...
'OPTIONS': {
...
'builtins': [
'path.to.csrf_esi',
],
}
}
]
清漆配置
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>
设置起来相当麻烦,但是一旦设置好,您就不必再看它了。