我正在使用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
....
我能做什么?
如果有人仍在关注这个问题,那么直接的答案就是你需要在view方法本身上使用装饰器。在get
类上定义的post
和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-based csrf tokens。您可以使用ensure_csrf_cookie
装饰器使django发送带有响应的csrftoken
cookie,只要您将该令牌包含为POST
标头,您的X-CSRFToken
请求就会生效。
你在这里遇到的问题是用于处理你的视图的django正在使用任何as_view()
方法将返回,而不是直接方法get()
或post()
。
因此,您应该使用以下方法之一装饰基于类的视图:
urlpatterns = patterns('', url('^login/$', csrf_exempt(views.LoginView.as_view())), ... )
dispatch()
方法(pre django 1.9)from django.utils.decorators import method_decorator class LoginView(APIView): @method_decorator(csrf_exempt) def dispatch(self, *args, **kwargs): ...
from django.utils.decorators import method_decorator @method_decorator(csrf_exempt, name='dispatch') class LoginView(APIView): ...
对于GET,您不应该修改数据,因此不需要CSRF。
如果您使用POST修改数据,那么如果您使用基于会话的身份验证,则应该有CSRF。否则,你正在打开一个安全漏洞。即使您认为您的Django服务器将要为iPhone应用程序提供服务,但没有什么可以阻止您的应用程序嗅探流量到您服务器的数据包,然后使用其他类型的Web客户端逆向工程访问服务器。因此,Django Rest Framework在某些情况下需要CSRF。这在Django rest framework documentation中提到。
围绕此POST要求的路径是不使用会话身份验证。例如,您可以通过HTTPS使用BasicAuthentication。使用此身份验证机制,您应该使用HTTPS来防止凭据在每个请求中以明文形式传递。
我有同样的问题。我的问题是我忘记将.as_view()
放在MyAPIView
上的urls.py中。所以它必须像:
url(r'$', GetLikesAPI.as_view(), name='list')
不:
url(r'$', GetLikesAPI, name='list')
在我的情况下它发生了因为我发送了put请求到url ='http://example.com/list/5'而没有斜线。当我将url更改为url ='http://example.com/list/5/'时,所有人都开始工作了。
这是一个老问题,但我们最近遇到了一些问题。
除非使用会话身份验证,否则DRF默认禁用CSRF。默认情况下,NSURLconnection设置为处理cookie。您需要明确告诉iOS应用不使用cookie。然后,如果需要,您可以继续使用会话身份验证,而不必让csrf免除您的意见。
urlpatterns = patterns('',
url('^login/$', csrf_exempt(views.LoginView.as_view())),
...
)
伙计们。我有同样的错误,并花了很多时间才发现:1)我有另一个路由器'登录',我错过'$'。我的意思是有时你可以忘记路由中的某些内容并获得此错误。