Django Rest框架删除csrf
我知道有关于Django Rest Framework的答案,但我找不到解决scheme。
我有一个应用程序具有身份validation和一些function。 我添加了一个新的应用程序,它使用Django Rest Framework。 我只想在这个应用程序中使用库。 另外,我想做POST请求,我总是收到这个回应:
{ "detail": "CSRF Failed: CSRF token missing or incorrect." }
我有以下代码:
# urls.py from django.conf.urls import patterns, url urlpatterns = patterns( 'api.views', url(r'^object/$', views.Object.as_view()), ) # views.py from rest_framework.views import APIView from rest_framework.response import Response from django.views.decorators.csrf import csrf_exempt class Object(APIView): @csrf_exempt def post(self, request, format=None): return Response({'received data': request.data})
我想添加API而不影响当前的应用程序。 所以我的问题是我怎么能禁用这个应用程序的CSRF?
为什么这个错误发生?
这是由于DRF使用默认的SessionAuthentication
scheme。 DRF的SessionAuthentication
使用Django的会话框架进行validation,这需要检查CSRF。
当你没有在view / viewset中定义任何的authentication_classes
时,DRF使用这个authentication类作为默认值。
'DEFAULT_AUTHENTICATION_CLASSES'= ( 'rest_framework.authentication.SessionAuthentication', 'rest_framework.authentication.BasicAuthentication' ),
由于DRF需要同时支持基于会话和非基于会话的身份validation,因此只对经过身份validation的用户执行CSRF检查。 这意味着只有经过身份validation的请求才需要CSRF令牌,并且匿名请求可以在没有CSRF令牌的情况下发送。
如果您在使用SessionAuthentication的AJAX风格API,则需要为任何“不安全”的HTTP方法调用(例如PUT, PATCH, POST or DELETE
请求)包含有效的CSRF令牌。
那该怎么办?
现在要禁用csrf检查,可以创build一个自定义的authentication类CsrfExemptSessionAuthentication
,该类从默认的SessionAuthentication
类扩展。 在这个authentication类中,我们将覆盖实际SessionAuthentication
内发生的enforce_csrf()
检查。
from rest_framework.authentication import SessionAuthentication, BasicAuthentication class CsrfExemptSessionAuthentication(SessionAuthentication): def enforce_csrf(self, request): return # To not perform the csrf check previously happening
在你看来,你可以定义authentication_classes
为:
authentication_classes = (CsrfExemptSessionAuthentication, BasicAuthentication)
这应该处理csrf错误。
更简单的解决scheme
在views.py中,使用大括号CsrfExemptMixin和authentication_classes:
# views.py from rest_framework.views import APIView from rest_framework.response import Response from django.views.decorators.csrf import csrf_exempt from braces.views import CsrfExemptMixin class Object(CsrfExemptMixin, APIView): authentication_classes = [] def post(self, request, format=None): return Response({'received data': request.data})
如果您不想使用基于会话的身份validation,则可以从REST_AUTHENTICATION_CLASSES中删除“会话身份validation”,并自动删除所有基于csrf的问题。 但在这种情况下,可浏览的API可能无法正常工作。 此外,即使使用会话身份validation,也不会出现此错误 您应该为您的apis使用像TokenAuthentication这样的自定义身份validation,并确保在您的请求中发送Accept:application/json
和Content-Type:application/json
(提供您正在使用json)以及身份validation令牌。
我感到同样的问题。 我跟着这个参考 ,它的工作。 解决scheme是创build一个中间件
在其中一个应用程序中添加disable.py文件(在我的例子中是'myapp')
class DisableCSRF(object): def process_request(self, request): setattr(request, '_dont_enforce_csrf_checks', True)
并将MIDDLEWARE添加到MIDDLEWARE_CLASSES
MIDDLEWARE_CLASSES = ( myapp.disable.DisableCSRF, )
您可能正在向可浏览的API发送数据,该数据库预期使用csrf格式。
如果您正在使用API,则可能需要发送JSON。 请确保你的头文件中的Content-Type
设置为application/json
,它不需要CSRF。
更多的上下文,比如带有标题的请求将有助于给出更准确的答案。
如果您正在为您的应用程序使用独占的虚拟环境,则可以使用以下方法,而无需使用任何其他应用程序。
您观察到的情况是因为rest_framework/authentication.py
在SessionAuthentication
类的authenticate
方法中包含以下代码:
self.enforce_csrf(request)
如果您不需要CSRF检查,则可以修改Request
类以拥有名为csrf_exempt
的属性,并在相应的View类csrf_exempt
其初始化为True
。 例如:
接下来,修改上面的代码如下:
if not request.csrf_exempt: self.enforce_csrf(request)
在Request
类中有一些相关的更改。 一个完整的实现可以在这里(完整的描述): https : //github.com/piaxis/django-rest-framework/commit/1bdb872bac5345202e2f58728d0e7fad70dfd7ed
对于所有谁没有帮助的答案。 是的,如果您没有使用SessionAuthentication
AUTHENTICATION CLASS,DRF会自动删除CSRF保护,例如许多开发人员只使用JWT:
'DEFAULT_AUTHENTICATION_CLASSES': ( 'rest_framework_jwt.authentication.JSONWebTokenAuthentication', ),
但CSRF not set
问题可能会由于某种原因而发生,例如你没有正确添加到你的path中查看:
url(r'^api/signup/', CreateUserView), # <= error! DRF cant remove CSRF because it is not as_view that does it!
代替
url(r'^api/signup/', CreateUserView.as_view()),