And*_*s E 10 django csrf varnish
我有一个Django视图,其中包含一个使用CSRF保护的表单.我希望在有正常的GET请求时由Varnish缓存此视图(因为所有用户都需要相同的表单,不需要登录).
所以有两个挑战:
如何在Varnish中缓存此页面而不向用户提供缓存/旧版本的csrf隐藏字段?是否可以使用CSRF字段缓存页面?
默认情况下,我的清漆会去掉所有的饼干,除了csrftoken饼干之外,我怎么能轻松地去掉所有的饼干?我是否必须设置特定的CSRF_COOKIE_DOMAIN?
在视图上使用CSRF本质上意味着视图的每个渲染本质上是不同的(即使只有一个隐藏字段的值正在改变).缓存在这种情况下不起作用.
但是,Django确实提供了绕过这种限制的机制,即cookie,正如您似乎已经猜到的那样.所以在你的第二部分,有两件事需要做:
CSRF_COOKIE_DOMAIN
如果请求来自不同的域而不是处理它,您只需要在Django中设置.
这是迟了几年,但这是我最近解决这个问题的方法.
诀窍是使用ESI,清漆支持.我们使用CSRF片段并将其粘贴到自己的页面中,包括通过ESI时通过清漆,以及其他方式(例如运行本地开发服务器时).
{% csrf_token %}
Run Code Online (Sandbox Code Playgroud)
{% if request.META.HTTP_X_VARNISH_USE_CACHE %}
<esi:include src="{% url 'esi_csrf_token' %}" />
{% else %}
{% include "csrf_esi.html" %}
{% endif %}
Run Code Online (Sandbox Code Playgroud)
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'),
]
Run Code Online (Sandbox Code Playgroud)
from django import template
register = template.Library()
@register.inclusion_tag('csrf_token.html', takes_context=True)
def csrf_token_esi(context):
return context
Run Code Online (Sandbox Code Playgroud)
TEMPLATES = [
{
...
'OPTIONS': {
...
'builtins': [
'path.to.csrf_esi',
],
}
}
]
Run Code Online (Sandbox Code Playgroud)
set req.http.X-Varnish-Use-Cache = true;
Run Code Online (Sandbox Code Playgroud)
您还需要将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>
Run Code Online (Sandbox Code Playgroud)
设置起来相当多,但是一旦你做到了,你就再也不用看了.
归档时间: |
|
查看次数: |
4301 次 |
最近记录: |