28

我正在使用 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
....

我能做些什么?

4

7 回答 7

21

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

因此,解决方案是将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 的 csrf tokens。您可以使用ensure_csrf_cookie装饰器让 django 发送一个csrftoken带有响应的 cookie,POST只要您将该令牌作为X-CSRFToken标头包含在内,您的请求就会验证。

于 2014-11-19T19:15:29.050 回答
11

I've had the same issue. My problem was that I forgot to put .as_view() in urls.py on MyAPIView. So it have to be like:

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

not:

url(r'$', GetLikesAPI, name='list')
于 2017-10-14T12:22:03.213 回答
7

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

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

  1. 在 urls.py
    urlpatterns = 模式('',
        url('^login/$', csrf_exempt(views.LoginView.as_view())),
        ...
    )
  1. dispatch()方法(pre django 1.9)
    从 django.utils.decorators 导入 method_decorator

    类登录视图(APIView):
       @method_decorator(csrf_exempt)
       def dispatch(self, *args, **kwargs):
           ...
  1. 或在类视图本身(来自 django 1.9)
    从 django.utils.decorators 导入 method_decorator


    @method_decorator(csrf_exempt, name='dispatch')
    类登录视图(APIView):
           ...
于 2017-03-21T09:27:04.300 回答
3

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

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

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

于 2013-07-31T03:57:23.987 回答
3
urlpatterns = patterns('',
       url('^login/$', csrf_exempt(views.LoginView.as_view())),
       ...
)

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

于 2018-04-24T20:46:51.547 回答
3

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

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

于 2015-08-17T15:51:06.607 回答
2

就我而言,它发生是因为我将 put 请求发送到 url=' http://example.com/list/5 ' 而最后没有斜线。当我将 url 更改为 url=' http://example.com/list/5/ ' 时,一切都开始工作了。

于 2018-01-02T14:59:19.557 回答