Django REST Framework CSRF 失败:未设置 CSRF cookie

Posted

技术标签:

【中文标题】Django REST Framework CSRF 失败:未设置 CSRF cookie【英文标题】:Django REST Framework CSRF Failed: CSRF cookie not set 【发布时间】:2013-05-12 02:05:01 【问题描述】:

我正在使用 django rest 框架通过 ios 执行 API 调用 我收到以下错误 “CSRF 失败:未设置 CSRF cookie。”

这是我的 django API 代码:

class LoginView(APIView):
    """
    List all snippets, or create a new snippet.
    """
    @csrf_exempt
    def get(self, request, format=None):
        startups = Startup.objects.all()
        serializer = StartupSerializer(startups, many=True)
        return Response(serializer.data)

    @csrf_exempt
    def post(self, request, format=None):
        profile = request.POST
....

我能做什么?

【问题讨论】:

你有没有想过这个问题?我从来没有通过这个。 Django Rest Framework remove csrf的可能重复 【参考方案1】:

对于 GET,您不应该修改数据,因此不需要 CSRF。

如果您使用 POST 修改数据,那么如果您使用基于会话的身份验证,则应该有一个 CSRF。否则,您将打开一个安全漏洞。即使您认为您的 Django 服务器将为 iPhone 应用程序提供服务,也没有什么可以阻止使用您的应用程序的人嗅探到您服务器的流量上的数据包,然后使用其他类型的 Web 客户端对服务器的访问进行逆向工程。出于这个原因,Django Rest Framework 在某些情况下需要 CSRF。 Django rest framework documentation中提到了这一点。

绕过这个 POST 要求的路径是不使用会话身份验证。例如,您可以通过 HTTPS 使用 BasicAuthentication。使用这种身份验证机制,您应该使用 HTTPS 来防止凭据在每个请求中以明文形式传递。

【讨论】:

> 我们的应用程序从流量上嗅探数据包 - https,所以不,这不是原因。 如果您可以接受禁用 CSRF 的风险,因为您认为您的数据包不安全并且不涉及浏览器,您应该尝试@Rahul Gupta-Iwasaki 的解决方案【参考方案2】:

如果还有人关注这个问题,直接回答是需要在视图方法本身上使用装饰器。在APIView 类上定义的getpost 方法只是告诉DRF 实际视图应该如何表现,但是在您调用LoginView.as_view() 之前,django 路由器期望的视图方法实际上并没有实例化。

因此,解决方案是将csrf_exempt 装饰器添加到urls.py。它可能如下所示:

#file: urls.py

from django.conf.urls import patterns, url
from django.views.decorators.csrf import csrf_exempt

import views

urlpatterns = patterns('',
    url('^login/$', csrf_exempt(views.LoginView.as_view())),
    ...
)

然而,正如 Mark 上面指出的,csrf 保护对于防止会话被劫持很重要。我自己没有使用过 iOS,但我会考虑使用 django 的 cookie-based csrf tokens。您可以使用 ensure_csrf_cookie 装饰器让 django 发送带有响应的 csrftoken cookie,只要您将该令牌包含为 X-CSRFToken 标头,您的 POST 请求就会验证。

【讨论】:

如果你使用路由器,你会怎么做?【参考方案3】:

这是一个老问题,但我们最近遇到了一些问题。

DRF 默认禁用 CSRF,除非使用会话身份验证。默认情况下 NSURLconnection 设置为处理 cookie。您需要明确告诉 iOS 应用不要使用 cookie。然后,如果需要,您可以继续使用会话身份验证,而不必 csrf 豁免您的视图。

【讨论】:

【参考方案4】:

您在这里遇到的问题是处理您的视图的 django 使用任何 as_view() 方法将返回,而不是直接方法 get()post()

因此,您应该通过以下方式之一装饰您的基于类的视图:

    在 urls.py 中
urlpatterns = 模式('', url('^login/$', csrf_exempt(views.LoginView.as_view())), ... )
    dispatch() 方法(django 1.9 前)
从 django.utils.decorators 导入 method_decorator 类登录视图(APIView): @method_decorator(csrf_exempt) def dispatch(self, *args, **kwargs): ...
    或在类视图本身上(来自 django 1.9)
从 django.utils.decorators 导入 method_decorator @method_decorator(csrf_exempt, name='dispatch') 类登录视图(APIView): ...

【讨论】:

【参考方案5】:

我也遇到了同样的问题。我的问题是我忘了把.as_view() 放在MyAPIView 的urls.py 中。所以它必须是这样的:

url(r'$', GetLikesAPI.as_view(), name='list')

不是:

url(r'$', GetLikesAPI, name='list')

【讨论】:

这种情况不太可能发生,因为如果你错过了as_view(),很可能整个路线都无法访问。 这是我的情况【参考方案6】:

在我的情况下,它发生是因为我将 put 请求发送到 url='http://example.com/list/5' 末尾没有斜线。当我将 url 更改为 url='http://example.com/list/5/' 时,一切都开始工作了。

【讨论】:

【参考方案7】:
urlpatterns = patterns('',
       url('^login/$', csrf_exempt(views.LoginView.as_view())),
       ...
)

伙计们。我有同样的错误,并花了很多时间才发现: 1)我有另一个带有“登录”的路由器,我错过了“$”。我的意思是有时您可能会在路由中忘记某些内容并出现此错误。

【讨论】:

以上是关于Django REST Framework CSRF 失败:未设置 CSRF cookie的主要内容,如果未能解决你的问题,请参考以下文章

怎么安装django rest framework

django rest framework中文介绍

17-Django-Django REST framework-REST framework及RESTful简介

为啥 django-rest-framework 不显示 OneToOneField 数据 - django

Django:rest framework之分页(Pagination)

django使用rest_framework