无法禁用 Django CSRF 框架并且正在破坏我的网站

Posted

技术标签:

【中文标题】无法禁用 Django CSRF 框架并且正在破坏我的网站【英文标题】:Django CSRF framework cannot be disabled and is breaking my site 【发布时间】:2010-12-11 16:16:47 【问题描述】:

django csrf 中间件不能被禁用。我已从项目的中间件中将其注释掉,但由于缺少 CSRF 问题,我的登录失败。我在 Django 后备箱工作。如果没有在中间件中启用 CSRF 会导致什么问题?

我必须禁用它,因为我的网站上有很多 CSRF 刚刚中断的 POST 请求。关于如何在 django 主干项目中完全禁用 CSRF 的任何反馈?

来自 Django 主干的“新”CSRF 框架还破坏了一个外部站点,该站点正在进入并在我提供给他们的 URL 上执行 POST(这是 restful API 的一部分。)我无法禁用CSRF 框架如我之前所说,我该如何解决这个问题?

【问题讨论】:

请采纳正确答案 来自@shreddd 的答案可能比公认的答案更好。 【参考方案1】:

一般来说,您不应该禁用 CSRF 保护,因为这样做会打开安全漏洞。不过,如果你坚持……

一种新的 CSRF 保护方法最近才登陆主干。您的网站是否仍然配置为使用旧方式?这里是the docs for The New Way™,这里是docs for The Old Way™。

【讨论】:

感谢您的信息,您没有告诉我如何完全禁用 CSRF,我有一个生产站点已停止为付费客户工作,因为我被这种“新”的做事方式蒙蔽了双眼那是不向后兼容的。但这是导致问题的原因,我正在努力快速更新到新的/旧的方式。 以下是开发者邮件列表中的一些讨论:groups.google.com/group/django-developers/browse_thread/thread/… 也许这将有助于禁用/更新。 有一个视图装饰器可以使用:@csrf_exempt,如果你放置这个装饰器,CSRF 框架将忽略它对该请求的检查。我仍然对这个 CSRF 陷阱是如何产生的感到很生气,它被纳入了 auth 框架,所以如果你使用 auth 登录,你就无法禁用它。 新版本刚刚登陆开发主干。您不应该将开发代码用于生产站点 - 或者如果您这样做,您应该在更新之前了解所有更改。 在他的辩护中,跟踪trunk 是运行 Django 很长一段时间的推荐方式。尽管情况发生了变化,但我相信仍有很多人这样做。【参考方案2】:

请参阅下面的答案以获得更好的解决方案。自从我写了这篇文章以来,发生了很多变化。现在有更好的方法来禁用 CSRF。

我感觉到你的痛苦。框架改变这样的基本功能是不可接受的。即使我想从现在开始使用它,我在同一台机器上的旧站点共享 django 的副本。像这样的更改应该需要主要版本号修订。 1.x --> 2.x。

无论如何,为了修复它,我只是将它注释掉并且不再经常更新 Django。

文件:django/middleware/csrf.py 第 160 行左右:

            # check incoming token
#            request_csrf_token = request.POST.get('csrfmiddlewaretoken', None)
#            if request_csrf_token != csrf_token:
#                if cookie_is_new:
#                    # probably a problem setting the CSRF cookie
#                    return reject("CSRF cookie not set.")
#                else:
#                    return reject("CSRF token missing or incorrect.")

【讨论】:

几年过去了,但对我来说评论这部分似乎仍然是最好的选择。其他解决方案通常适用于某些但并非所有情况。【参考方案3】:

是的,可以禁用 Django csrf 框架。

要手动排除任何 CSRF 中间件处理的视图函数,您可以使用 django.views.decorators.csrf 模块中的 csrf_exempt 装饰器。例如:(see doc)

from django.views.decorators.csrf import csrf_exempt                                          
@csrf_exempt                                                                                  
def my_view:                                                                            
    return Httpresponse("hello world")

..然后从模板中删除表单中的% csrf_token %,或者如果您没有将其包含在表单中,则其他内容保持不变。

【讨论】:

+1 使用规定的方法选择性地关闭它要好得多,而不是到处关闭它! 我同意这应该是公认的答案。一般来说,当 API 已经提供了你需要的功能时,不要破解库。 如果您想在新项目中重用旧应用程序,这真的很棒。 这不是公认的答案,因为他很可能使用urls.py 中的默认登录名,如下所示:url(r'^accounts/login/$', 'django.contrib.auth.views.login', 'template_name': 'login.html', name='login'), 提醒:如果您在同一个视图中有其他装饰器,则顺序是相关的:所以先放置@csrf_exempt。【参考方案4】:

我只是尝试从我的 settings.py 中删除对 csrf 中间件类的引用,它成功了。不确定这是否可以接受。有cmets吗? 以下两行被删除 -

      'django.middleware.csrf.CsrfViewMiddleware',
      'django.middleware.csrf.CsrfResponseMiddleware',

【讨论】:

好的,知道了。它破坏了我的管理内容,因此,补丁解决方案似乎是最好的(虽然没有尝试过)。【参考方案5】:

您可以在中间件中禁用此功能。

在你的 settings.py 中添加一行到 MIDDLEWARE_CLASSES:

MIDDLEWARE_CLASSES = (

    myapp.disable.DisableCSRF, 

)

使用以下内容在 myapp 中创建一个 disable.py

class DisableCSRF(object):
    def process_request(self, request):
        setattr(request, '_dont_enforce_csrf_checks', True)

基本上如果你在你的请求中设置了_dont_enforce_csrf_checks,你应该没问题。

【讨论】:

谢谢!正是我需要的。我使用 Django 的评论系统,但由于包含表单的页面被缓存,csrf 验证不起作用。 这是禁用整个站点的csrf的最佳方法,非常简单。要选择性地禁用,这不是问题,那么您可以使用关于 @csrf_exempt 的其他答案 这个就是那个,之前的其他都太笼统了,或者只是掩盖了 csrf 视图失败的事实。这个正确地禁用了某些应用程序,而不伪装失败...... 这也适用于 Django Rest Framework。我在同时使用 View 和 ResponseMixin 时遇到问题。【参考方案6】:

我的 django 版本是 1.11。中间件应该是这样的:

from django.utils.deprecation import MiddlewareMixin


class DisableCSRF(MiddlewareMixin):
    def process_request(self, request):
        setattr(request, '_dont_enforce_csrf_checks', True)

【讨论】:

以上是关于无法禁用 Django CSRF 框架并且正在破坏我的网站的主要内容,如果未能解决你的问题,请参考以下文章

在 api 视图方法上禁用 CSRF(django rest 框架)

你如何在 django rest 框架中实现 CSRF 令牌?

如何将 django csrf 令牌直接嵌入 HTML?

如何忽略发送到 Django REST 框架的 CSRF 令牌?

如何仅在某些情况下禁用 Django 的 csrf 保护?

Django学习之禁用csrf和使用csrf操作详解