无模板 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()

猴子补丁 APIView 创建一个 CSRFCookie mixin 并将其添加到您的视图中 将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 令牌是不是在浏览会话过程中更新?的主要内容,如果未能解决你的问题,请参考以下文章

Django使用Ajax实现页面无刷新评论回复功能

Django/Ajax 发送“无”值来查看

来自 django 模板的 Ajax 调用

django使用模板视图和ajax

AJAX成功的Django渲染模板

Django - 渲染模板并通过 AJAX 传递它们