为啥 Django 不在 Varnish 代理后面生成 CSRF 或会话 Cookie?
Posted
技术标签:
【中文标题】为啥 Django 不在 Varnish 代理后面生成 CSRF 或会话 Cookie?【英文标题】:Why does Django not generate CSRF or Session Cookies behind a Varnish Proxy?为什么 Django 不在 Varnish 代理后面生成 CSRF 或会话 Cookie? 【发布时间】:2011-08-29 06:14:33 【问题描述】:在带有 Apache2 的 Linux 服务器上运行 Django 1.2.5,由于某种原因,Django 似乎无法存储 CSRF 或会话 cookie。因此,当我尝试登录 Django 管理员时,它会在提交登录表单时给我一个 CSRF 验证错误。有没有人提出反对并找到解决方案?
当我在我的主机提供的 VPS 的 url 上尝试此操作时,我能够发布有效的帖子。示例:vps123.hostdomain.com/admin/ 并为该域设置了 cookie。但是,当我转到 www.sitedomain.com/admin/ 并尝试登录时,我收到一个 CSRF 403 错误,提示该 cookie 不存在,并且当我检查我的浏览器 cookie 时,它们没有设置。
我已尝试在我的设置文件中设置以下内容:
SESSION_COOKIE_DOMAIN = 'www.sitedomain.com'
CSRF_COOKIE_DOMAIN = 'www.sitedomain.com'
也试过了:
SESSION_COOKIE_DOMAIN = 'vps123.hostdomain.com'
CSRF_COOKIE_DOMAIN = 'vps123.hostdomain.com'
我在 settings.py 中的 MIDDLEWARE_CLASSES 中添加了“django.middleware.csrf.CsrfViewMiddleware”,并且表单中有一个 CSRF 令牌,它显示在 POST 中。
我启用了 cookie。我在多个浏览器和机器上都试过了。
www.sitedomain.com 前面有一个清漆代理服务器,我认为这可能是问题的一部分。任何有使用代理服务器和 Django 经验的人都可以对此有所了解。
我的 apache2 配置:
NameVirtualHost *:80
<VirtualHost *:80>
ServerName www.sitedomain.com
ServerAlias www.sitedomain.com
<Location "/">
Options FollowSymLinks
SetHandler python-program
PythonInterpreter nzsite
PythonHandler django.core.handlers.modpython
PythonDebug On
PythonPath "['/var/www/django_projects', '/var/www', '/usr/lib/python2.6/dist-packages'] + sys.path"
SetEnv DJANGO_SETTINGS_MODULE project_one.settings
</Location>
<location "/phpmyadmin">
SetHandler None
</location>
</VirtualHost>
<VirtualHost *:80>
ServerName othersite.sitedomain.com
ServerAlias othersite.sitedomain.com
<Location "/">
Options FollowSymLinks
SetHandler python-program
PythonInterpreter ausite
PythonHandler django.core.handlers.modpython
PythonDebug On
PythonPath "['/var/www/django_projects', '/var/www', '/usr/lib/python2.6/dist-packages'] + sys.path"
SetEnv DJANGO_SETTINGS_MODULE project_two.settings
</Location>
<location "/phpmyadmin">
SetHandler None
</location>
</VirtualHost>
【问题讨论】:
我认为这个问题太复杂了,没有:apache 设置、django 设置等... exact 相同的代码是否使用内置开发服务器工作? 我编辑了我的问题以显示更多细节。谢谢! 有点离题,但有什么理由必须使用 modpython 吗? 使用开发服务器时是否设置了 cookie? @Josh,一点帮助都没有。你会建议什么来代替它? 【参考方案1】:问题是我的站点前面有一个 Varnish 代理服务器。 Varnish 正在接受请求并从他们那里删除 cookie。为了解决这个问题,我必须让管理 Varnish 服务器的公司将“/admin”添加到异常列表中,以便可以传递 cookie。抱歉,我无法详细说明 Varnish 流程的工作原理。
【讨论】:
哦,这很有趣!只有管理站点没有成功使用 CSRF 吗?我还想象任何未来具有表单的 URL 都需要添加到例外列表中。我是否可以建议编辑您的问题的标题以包含单词 varnish proxy,以便将来遇到此问题的用户能够轻松找到此答案?【参考方案2】:您是否在表单模板中包含csrf_token
?
<form autocomplete="off" method="post" action="% url auth_login %">% csrf_token %
form|as_p
<input type='submit' />
</form>
包括中间件?
'django.middleware.csrf.CsrfViewMiddleware',
从您的编辑推测,它可能与 Apache 中的 VirtualHost 配置有关(如果您的提供商使用的是 apache)。这是我的一个 apache 配置的编辑版本。
<VirtualHost *:80>
ServerName www.domain.com
WSGIProcessGroup my-django-site
WSGIScriptAlias / /path-to-my-django-site/wsgi/production.wsgi
Alias /media /path-to-my-django-site/media
</VirtualHost>
可能是 apache 中的服务器名称必须与您点击框的域名以及 Django 配置中的 *_COOKIE_DOMAIN 设置相匹配。我不确定你是否能够改变这一点。如果没有其他答案可以取胜,可能值得与您的提供商交谈。
【讨论】:
【参考方案3】:您是否正在使用 csrf 信息更新您的模板数据?
from django.core.context_processors import csrf
def index(request)
data = "listitems": items
data.updates(csrf(request))
return render_to_response('template.html', data)
【讨论】:
如果您返回 context_instance=RequestContext(request),则不需要您的建议。以上是关于为啥 Django 不在 Varnish 代理后面生成 CSRF 或会话 Cookie?的主要内容,如果未能解决你的问题,请参考以下文章