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

时间:2022-06-20 07:04:02

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?

我能做什么?

7 个解决方案

#1


12  

If anyone is still following this question, the direct answer is that you need to use the decorator on the view method itself. The get and post methods defined on the APIView class 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().

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

Thus, the solution is to add the csrf_exempt decorator 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 hijacked. 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_cookie decorator to make django send a csrftoken cookie with a response, and your POST requests will validate as long as you include that token as an X-CSRFToken header.

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

#2


1  

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来防止凭据在每个请求中以明文形式传递。

#3


1  

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
  2. 在urls.py中
    urlpatterns = patterns('',
        url('^login/$', csrf_exempt(views.LoginView.as_view())),
        ...
    )
  1. or on dispatch() method (pre django 1.9)
  2. 或者在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. or on class view itself (from django 1.9)
  2. 或者在课堂视图上(来自django 1.9)
    from django.utils.decorators import method_decorator


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

#4


1  

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/'时,所有内容都开始起作用。

#5


1  

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

我有同样的问题。我的问题是我忘记在MyAPIView上的urls.py中添加.as_view()。所以它需要像:

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

not:

不:

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

#6


0  

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免除您的意见。

#7


0  

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)我有另一个路由器'登录',我错过了'$'。我的意思是有时你可以忘记路由中的某些内容并获得此错误。

#1


12  

If anyone is still following this question, the direct answer is that you need to use the decorator on the view method itself. The get and post methods defined on the APIView class 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().

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

Thus, the solution is to add the csrf_exempt decorator 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 hijacked. 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_cookie decorator to make django send a csrftoken cookie with a response, and your POST requests will validate as long as you include that token as an X-CSRFToken header.

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

#2


1  

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来防止凭据在每个请求中以明文形式传递。

#3


1  

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
  2. 在urls.py中
    urlpatterns = patterns('',
        url('^login/$', csrf_exempt(views.LoginView.as_view())),
        ...
    )
  1. or on dispatch() method (pre django 1.9)
  2. 或者在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. or on class view itself (from django 1.9)
  2. 或者在课堂视图上(来自django 1.9)
    from django.utils.decorators import method_decorator


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

#4


1  

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/'时,所有内容都开始起作用。

#5


1  

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

我有同样的问题。我的问题是我忘记在MyAPIView上的urls.py中添加.as_view()。所以它需要像:

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

not:

不:

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

#6


0  

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免除您的意见。

#7


0  

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)我有另一个路由器'登录',我错过了'$'。我的意思是有时你可以忘记路由中的某些内容并获得此错误。