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

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/16599979/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-08-18 23:07:36  来源:igfitidea点击:

Django REST Framework CSRF Failed: CSRF cookie not set

pythondjangodjango-viewsdjango-rest-framework

提问by user2237822

I am using the django rest framework to perform API calls via IOS and I get the following error "CSRF Failed: CSRF cookie not set."

我正在使用 django rest 框架通过 IOS 执行 API 调用,但出现以下错误“CSRF 失败:CSRF cookie 未设置”。

Here's my django API code:

这是我的 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
....

What can I do?

我能做什么?

回答by Mark Chackerian

For GETs, you shouldn't be modifying data, so a CSRF isn't required.

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

If you are modifying data with a POST, then you SHOULD have a CSRF if you are using session based authentication. Otherwise, you're opening up a security hole. Even though you think your Django server is going to be servicing iPhone apps, there's nothing to stop someone with your app from sniffing the packets on the traffic to your server, and then reverse engineering access to the server with other kinds of web clients. For this reason, Django Rest Framework requires a CSRF in some cases. This is mentioned in the Django rest framework documentation.

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

The path around this requirement for POSTs is to not use session authentication. For example, you could use BasicAuthentication over HTTPS. With this authentication mechanism, you should use HTTPS to prevent credentials from being passed in the clear with every request.

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

回答by Rahul Gupta-Iwasaki

If anyone is still following this question, the direct answer is that you need to use the decorator on the view method itself. The getand postmethods defined on the APIViewclass just tell DRF how the actual view should behave, but the view method that the django router expects is not actually instantiated until you call LoginView.as_view().

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

Thus, the solution is to add the csrf_exemptdecorator to urls.py. It might look as follows:

因此,解决方案是将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())),
    ...
)

However, as Mark points out above, csrf protection is important to prevent your sessions from being hiHymaned. I haven't worked with iOS myself, but I would look into using django's cookie-based csrf tokens. You can use the ensure_csrf_cookiedecorator to make django send a csrftokencookie with a response, and your POSTrequests will validate as long as you include that token as an X-CSRFTokenheader.

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

回答by kevswanberg

This is an old question but something we ran into recently.

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

DRF disables CSRF by default, unless using session authentication. By default NSURLconnection is set up to handle cookies. You need to explicitly tell the iOS app to not use cookies. Then you can keep using session auth if needed and not have to csrf exempt your views.

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

回答by thedk

The problem you encounter here is that django for processing your view is using whatever as_view()method will return, not directly method get()or post().

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

Therefore you should decorate your class-based view in one of following ways:

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

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

    class LoginView(APIView):
       @method_decorator(csrf_exempt)
       def dispatch(self, *args, **kwargs):
           ...
  1. or on class view itself (from django 1.9)
  1. 或在类视图本身(来自 django 1.9)
    from django.utils.decorators import method_decorator


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

回答by М.Б.

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:

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

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

not:

不是:

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

回答by Radren

In my case it happend because I sent put request to url='http://example.com/list/5' without slash at the end. When I changed url to url='http://example.com/list/5/' all started to work.

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

回答by Df.fpm

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

Guys. I had the same error and spent a lot of time just for finding that: 1) I had another router with 'login' and there i missed '$'. I mean sometimes you can forget something in routing and get this error.

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