无法禁用 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 令牌?