无模板 Django + AJAX:Django 的 CSRF 令牌是不是在浏览会话过程中更新?
Posted
技术标签:
【中文标题】无模板 Django + AJAX:Django 的 CSRF 令牌是不是在浏览会话过程中更新?【英文标题】:Template-less Django + AJAX: Does Django's CSRF token get updated during the course of a browsing session?无模板 Django + AJAX:Django 的 CSRF 令牌是否在浏览会话过程中更新? 【发布时间】:2013-12-20 03:07:18 【问题描述】:我目前的设置是 AngularJS + Django 1.5,我完全放弃了使用 Django 的模板引擎(即后端几乎是一个 API 服务器)。
由于我没有使用 csrf_token
模板标签,因此 Django 不会设置和发送 csrftoken
cookie 作为响应。按照官方文档的指示,应该使用ensure_csrf_cookie()
装饰器来强制装饰视图发送csrftoken
cookie。
我已将ensure_csrf_cookie()
装饰器应用于视图,它为我的Web 客户端在引导时调用的第一个GET 请求提供服务。这样,我的 Web 客户端就获得了 CSRF 令牌,此后就可以向服务器调用不安全的方法(例如 POST)。
只有在浏览会话结束之前 CSRF 令牌保持不变时,上述设置才能正常工作。
问题: Django 的 CSRF 令牌会在浏览会话期间更新吗?如果“是”,这是否意味着我需要将 ensure_csrf_cookie()
装饰器应用于我拥有的所有视图?
【问题讨论】:
1) 不太可能,但恕我直言,这是一个实现细节,我建议不要依赖这种行为。 2) 只需编写一个由ensure_csrf_cookie()
修饰的 Mixin 或 View 基类,并将其用作 API 视图的基础(可能还有很多样板代码您也可以移到那里)。
谢谢@PauloScardine。我同意你所说的。如果为所有服务器响应设置了 csrf 令牌 cookie,会不会有任何安全隐患?
AFAIK 没有安全隐患,像 Django-REST-Framework 这样的框架可以做到这一点——事实上,你应该在下一个项目中考虑它,因为它为你提供了诸如分页、节流和花哨的权限系统之类的东西。
@PauloScardine - 哈哈。我正在为当前项目使用 Django REST Framework。我喜欢它。但我没有看到 rest_framework 在其基本视图(即 APIView)或其任何通用视图中强制 CSRF cookie。我错过了什么吗?请注意,我有 rest_framework v2.3.8。
您是否启用了基于会话的身份验证?
【参考方案1】:
1) Django 的 CSRF 令牌是否会在浏览会话期间更新?
看起来CSRF 令牌在每个会话中都是唯一的,但它基于我的观察,我没有“官方”来源。使用 Angular.js,我可以毫无问题地使用以下代码:
angular.module('app', ...)
.config(function($httpProvider)
var cookies = document.cookie.split(';');
var csrftoken = _.find(cookies, function(v)
return v.trim().indexOf('csrftoken=') == 0;
);
if(csrftoken)
$httpProvider.defaults.headers.common['X-CSRFToken'] = csrftoken.split('=')[1];
)
由于我从 Django 提供 html,所以当 Angular 引导时,cookie 已经存在。
2) 如果“是”,这是否意味着我需要将 ensure_csrf_cookie() 装饰器应用于我拥有的所有视图?
如果CSRF,您可以尝试CORS。 Otto Yiu 维护 django-cors-headers 包,已知它可以与 REST 框架 API 一起正常工作。
一些(未经测试的)想法可以应用ensure_csrf_cookie()
:
ensure_csrf_cookie()
应用于您的基类
【讨论】:
【参考方案2】:支持@Paulo Scardine 应用ensure_csrf_cookie()
的想法(我认为这是有效且有用的),如果您绝对需要ensure_csrf_cookie()
,我想为其添加一个新的可能解决方案你的意见。您可以编写自定义middleware
,并实现ensure_csrf_cookie
中的逻辑。像这样的:
在你的app.middleware.py
:
from django.middleware.csrf import get_token
class EnsureCsrfCookie(object):
def process_request(self, request):
# Forces process_response to send the cookie
get_token(request)
您的settings
文件中的课程将中间件添加到MIDDLEWARE_CLASSES
:
MIDDLEWARE_CLASSES = (
.,
.,
.,
'app.middleware.EnsureCsrfCookie',
.,
.,
.,
)
面对这个问题只是一个想法。我希望它对将来的某些人有用。
【讨论】:
以上是关于无模板 Django + AJAX:Django 的 CSRF 令牌是不是在浏览会话过程中更新?的主要内容,如果未能解决你的问题,请参考以下文章