Django REST框架CSRF失败:未设置CSRF cookie

问题描述 投票:19回答:7

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

我能做什么?

python django django-views django-rest-framework
7个回答
14
投票

如果有人仍在关注这个问题,那么直接的答案就是你需要在view方法本身上使用装饰器。在get类上定义的postAPIView方法只是告诉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-based csrf tokens。您可以使用ensure_csrf_cookie装饰器使django发送带有响应的csrftoken cookie,只要您将该令牌包含为POST标头,您的X-CSRFToken请求就会生效。


3
投票

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

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

  1. 在urls.py中
    urlpatterns = patterns('',
        url('^login/$', csrf_exempt(views.LoginView.as_view())),
        ...
    )
  1. 或者在dispatch()方法(pre django 1.9)
    from django.utils.decorators import method_decorator

    class LoginView(APIView):
       @method_decorator(csrf_exempt)
       def dispatch(self, *args, **kwargs):
           ...
  1. 或者在课堂视图上(来自django 1.9)
    from django.utils.decorators import method_decorator


    @method_decorator(csrf_exempt, name='dispatch')
    class LoginView(APIView):
           ...

2
投票

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

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

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


2
投票

我有同样的问题。我的问题是我忘记将.as_view()放在MyAPIView上的urls.py中。所以它必须像:

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

不:

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

1
投票

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


0
投票

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

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


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

伙计们。我有同样的错误,并花了很多时间才发现:1)我有另一个路由器'登录',我错过'$'。我的意思是有时你可以忘记路由中的某些内容并获得此错误。

© www.soinside.com 2019 - 2024. All rights reserved.