Django Rest框架删除csrf
我知道有关于Django Rest框架的答案,但我找不到解决问题的方法 我有一个应用程序,它具有身份验证和一些功能。 我向它添加了一个新的应用程序,它使用Django Rest框架。我只想在此应用程序中使用库。我还想提出POST请求,我总是收到以下回复:Django Rest框架删除csrf,django,django-rest-framework,csrf,django-csrf,Django,Django Rest Framework,Csrf,Django Csrf,我知道有关于Django Rest框架的答案,但我找不到解决问题的方法 我有一个应用程序,它具有身份验证和一些功能。 我向它添加了一个新的应用程序,它使用Django Rest框架。我只想在此应用程序中使用库。我还想提出POST请求,我总是收到以下回复: { "detail": "CSRF Failed: CSRF token missing or incorrect." } 我有以下代码: # urls.py from django.conf.urls import patterns
{
"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?如果您不想使用基于会话的身份验证,您可以从REST\u身份验证\u类中删除
会话身份验证
,这将自动删除所有基于CSRF的问题。但在这种情况下,可浏览的API可能无法工作
此外,即使会话身份验证也不应出现此错误。您应该为API使用自定义身份验证,如TokenAuthentication,并确保在请求中随身份验证令牌一起发送
Accept:application/json
和Content-Type:application/json
(如果您使用的是json)。为什么会发生此错误?
发生这种情况是因为DRF使用默认的SessionAuthentication
方案。DRF的会话身份验证使用Django的会话框架进行身份验证,需要检查CSRF
如果在视图/视图集中未定义任何身份验证\u类
,DRF将使用此身份验证类作为默认类
'DEFAULT_AUTHENTICATION_CLASSES'= (
'rest_framework.authentication.SessionAuthentication',
'rest_framework.authentication.BasicAuthentication'
),
由于DRF需要支持对同一视图的基于会话和基于非会话的身份验证,因此它只对经过身份验证的用户实施CSRF检查。这意味着只有经过身份验证的请求需要CSRF令牌,而匿名请求可以在没有CSRF令牌的情况下发送
如果您使用的是带有SessionAuthentication的AJAX风格的API,则需要为任何“不安全”HTTP方法调用包括有效的CSRF令牌,例如PUT、PATCH、POST或DELETE
请求
那怎么办?
现在要禁用csrf检查,您可以创建一个自定义身份验证类CsrfExemptSessionAuthentication
,该类扩展自默认的SessionAuthentication
类。在这个身份验证类中,我们将覆盖在实际的会话身份验证中发生的强制\u 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
在您的视图中,您可以将身份验证\u类定义为:
authentication_classes = (CsrfExemptSessionAuthentication, BasicAuthentication)
这应该可以处理csrf错误。我也遇到了同样的问题。我遵循这一点,它起了作用。
解决方案是创建一个中间件
在您的一个应用程序中添加disable.py文件(在我的示例中是“myapp”)
并将中间件添加到中间件类中
MIDDLEWARE_CLASSES = (
myapp.disable.DisableCSRF,
)
更简单的解决方案:
在views.py中,使用django大括号“CsrfExemptMixin
和authentication\u class
:
# 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})
如果您正在为您的应用程序使用专用虚拟环境,则可以使用以下方法,而无需使用任何其他有效的应用程序
您观察到的情况是因为rest\u framework/authentication.py
在authenticate
方法的SessionAuthentication
类中有此代码:
self.enforce_csrf(request)
如果不希望进行csrf检查,可以修改Request
类,使其具有名为csrf_-emption
的属性,并在相应的视图类中将其初始化为True
。例如:
接下来,修改上述代码如下:
if not request.csrf_exempt:
self.enforce_csrf(request)
对于所有没有找到有用答案的人,您必须在请求
类中进行一些相关更改。是如果您不使用SessionAuthentication
AUTHENTICATION类,DRF会自动删除CSRF保护,例如,许多开发人员只使用JWT:
'DEFAULT_AUTHENTICATION_CLASSES': (
'rest_framework_jwt.authentication.JSONWebTokenAuthentication',
),
但问题CSRF not set
可能是由于其他原因造成的,例如您没有正确地将路径添加到视图中:
url(r'^api/signup/', CreateUserView), # <= error! DRF cant remove CSRF because it is not as_view that does it!
我的解决方案显示为blow。装饰一下我的班级
from django.views.decorators.csrf import csrf_exempt
@method_decorator(csrf_exempt, name='dispatch')
@method_decorator(basic_auth_required(
target_test=lambda request: not request.user.is_authenticated
), name='dispatch')
class GenPedigreeView(View):
pass
修改URL.py
如果在urls.py中管理路由,则可以使用csrf_emption()包装所需的路由,以将其从csrf验证中间件中排除
from django.conf.urls import patterns, url
from django.views.decorators.csrf import csrf_exempt
import views
urlpatterns = patterns('',
url(r'^object/$', csrf_exempt(views.ObjectView.as_view())),
...
)
或者,作为一名装饰师
有些人可能会发现使用@csrf_豁免装饰器更适合他们的需要
比如说,
from django.views.decorators.csrf import csrf_exempt
from django.http import HttpResponse
@csrf_exempt
def my_view(request):
return HttpResponse('Hello world')
应该把工作做完 这也可能是一个问题
在DNS更改之间,这也是一个因素。如果DNS在出现问题/更改之前工作,等待DNS完全刷新将解决此问题。我尝试了上面的一些答案,觉得创建单独的类有点过火
作为参考,我在尝试将基于函数的视图方法更新为基于类的视图方法以进行用户注册时遇到了这个问题
使用基于类的视图(CBV)和Django Rest Framework(DRF)时,从ApiView类继承,并将权限类和身份验证类设置为空元组。下面是一个例子
class UserRegistrationView(APIView):
permission_classes = ()
authentication_classes = ()
def post(self, request, *args, **kwargs):
# rest of your code here
使用RESTAPI POST时,缺少X-CSRFToken请求头可能会导致该错误。
提供从JS获取和设置CSRF令牌值的示例代码
正如上面的答案所指出的,CSRF检查在使用SessionAuthentication时发生。另一种方法是使用TokenAuthentication,但请记住,它应该放在REST\u FRAMEWORK设置的默认\u AUTHENTICATION\u类列表的第一位。您需要添加此项以防止默认会话验证:(settings.py)
然后:(views.py)
取消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
我在尝试向JWT进行身份验证并执行POST请求时遇到了相同的问题
我的初始设置如下所示:
REST_FRAMEWORK = {
"DEFAULT_AUTHENTICATION_CLASSES": (
"rest_framework.authentication.SessionAuthentication",
"django_cognito_jwt.JSONWebTokenAuthentication",
),
...
}
AsSessionAuthentication
在列表中首先被选中
REST_FRAMEWORK = {
'DEFAULT_AUTHENTICATION_CLASSES': (
'rest_framework.authentication.TokenAuthentication',
),
'DEFAULT_PERMISSION_CLASSES': (
'rest_framework.permissions.IsAuthenticated',
)
}
from rest_framework.permissions import AllowAny
class Abc(APIView):
permission_classes = (AllowAny,)
def ...():
REST_FRAMEWORK = {
"DEFAULT_AUTHENTICATION_CLASSES": (
"rest_framework.authentication.SessionAuthentication",
"django_cognito_jwt.JSONWebTokenAuthentication",
),
...
}
"DEFAULT_AUTHENTICATION_CLASSES": (
"django_cognito_jwt.JSONWebTokenAuthentication",
"rest_framework.authentication.SessionAuthentication",
),
@api_view(['POST'])
@permission_classes((IsAuthenticated, ))
def create_transaction(request):
return Response(status=status.HTTP_200_OK)
def create_transaction(initial_data):
pass
urlpatterns = [
path('transaction', views.create_transaction, name='transaction'),
]