Ire*_*xas 95 django csrf django-csrf django-rest-framework
我知道有关于Django Rest Framework的答案,但我无法找到解决问题的方法.
我有一个具有身份验证和一些功能的应用程序.我添加了一个新的应用程序,它使用Django Rest Framework.我想只在这个应用程序中使用该库.我也想发出POST请求,我总是收到这个回复:
{
"detail": "CSRF Failed: CSRF token missing or incorrect."
}
Run Code Online (Sandbox Code Playgroud)
我有以下代码:
# 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})
Run Code Online (Sandbox Code Playgroud)
我想添加API而不影响当前的应用程序.所以我的问题是如何才能为此应用禁用CSRF?
Rah*_*pta 190
为什么会出现这种错误?
这是因为SessionAuthenticationDRF使用的默认方案.DRF SessionAuthentication使用Django的会话框架进行身份验证,需要检查CSRF.
如果未authentication_classes在视图/视图集中定义任何内容,DRF将使用此身份验证类作为默认值.
'DEFAULT_AUTHENTICATION_CLASSES'= (
'rest_framework.authentication.SessionAuthentication',
'rest_framework.authentication.BasicAuthentication'
),
Run Code Online (Sandbox Code Playgroud)
由于DRF需要支持对相同视图的会话和非会话身份验证,因此它仅对经过身份验证的用户执行CSRF检查.这意味着只有经过身份验证的请求才需要CSRF令牌,并且可以在没有CSRF令牌的情况下发送匿名请求.
如果您使用带有SessionAuthentication的AJAX样式API,则需要为任何"不安全"HTTP方法调用(例如PUT, PATCH, POST or DELETE请求)包含有效的CSRF令牌.
该怎么办?
现在要禁用csrf检查,您可以创建一个CsrfExemptSessionAuthentication从默认SessionAuthentication类扩展的自定义身份验证类.在此身份验证类中,我们将覆盖enforce_csrf()实际内部发生的检查SessionAuthentication.
from rest_framework.authentication import SessionAuthentication, BasicAuthentication
class CsrfExemptSessionAuthentication(SessionAuthentication):
def enforce_csrf(self, request):
return # To not perform the csrf check previously happening
Run Code Online (Sandbox Code Playgroud)
在您的视图中,您可以将其定义authentication_classes为:
authentication_classes = (CsrfExemptSessionAuthentication, BasicAuthentication)
Run Code Online (Sandbox Code Playgroud)
这应该处理csrf错误.
bix*_*e57 15
更简单的解决方案
在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})
Run Code Online (Sandbox Code Playgroud)
Sye*_*zan 12
修改urls.py
如果您在urls.py中管理路由,则可以使用csrf_exempt()包装所需的路由,以将它们从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())),
...
)
Run Code Online (Sandbox Code Playgroud)
或者,作为装饰器,有些人可能会发现使用@csrf_exempt装饰器更适合他们的需要
例如,
from django.views.decorators.csrf import csrf_exempt
from django.http import HttpResponse
@csrf_exempt
def my_view(request):
return HttpResponse('Hello world')
Run Code Online (Sandbox Code Playgroud)
应该完成工作!
对于所有没有找到有用答案的人.是,如果您不使用SessionAuthenticationAUTHENTICATION CLASS,DRF会自动删除CSRF保护,例如,许多开发人员仅使用JWT:
'DEFAULT_AUTHENTICATION_CLASSES': (
'rest_framework_jwt.authentication.JSONWebTokenAuthentication',
),
Run Code Online (Sandbox Code Playgroud)
但问题CSRF not set可能是由于另一个原因造成的,例如,您没有正确添加路径给您查看:
url(r'^api/signup/', CreateUserView), # <= error! DRF cant remove CSRF because it is not as_view that does it!
Run Code Online (Sandbox Code Playgroud)
代替
url(r'^api/signup/', CreateUserView.as_view()),
Run Code Online (Sandbox Code Playgroud)
如果您不想使用基于会话的身份验证,则可以Session Authentication从REST_AUTHENTICATION_CLASSES中删除,这将自动删除所有基于csrf的问题.但在这种情况下,Browseable apis可能无法正常工作.
此外,即使使用会话身份验证,也不会出现此错误 您应该为您的api使用TokenAuthentication等自定义身份验证,并确保在您的请求中发送Accept:application/json和Content-Type:application/json(如果您使用的是json)以及身份验证令牌.
我尝试了上面的一些答案,并觉得创建一个单独的类有点麻烦。
作为参考,当尝试将基于函数的视图方法更新为用于用户注册的基于类的视图方法时,我遇到了此问题。
使用基于类的视图(CBV)和Django Rest框架(DRF)时,从ApiView类继承,并将Permission_classes和authentication_classes设置为空元组。在下面找到一个例子。
class UserRegistrationView(APIView):
permission_classes = ()
authentication_classes = ()
def post(self, request, *args, **kwargs):
# rest of your code here
Run Code Online (Sandbox Code Playgroud)
您需要添加此内容以防止默认会话身份验证:(settings.py)
REST_FRAMEWORK = {
'DEFAULT_AUTHENTICATION_CLASSES': (
'rest_framework.authentication.TokenAuthentication',
),
'DEFAULT_PERMISSION_CLASSES': (
'rest_framework.permissions.IsAuthenticated',
)
}
Run Code Online (Sandbox Code Playgroud)
然后:(views.py)
from rest_framework.permissions import AllowAny
class Abc(APIView):
permission_classes = (AllowAny,)
def ...():
Run Code Online (Sandbox Code Playgroud)
authentication.py并将其放置在项目中您想要的任何位置。例如,在文件夹session_utils.from rest_framework.authentication import SessionAuthentication\n\n\nclass SessionCsrfExemptAuthentication(SessionAuthentication):\n def enforce_csrf(self, request):\n pass\n\nRun Code Online (Sandbox Code Playgroud)\nPOST、PUT、PATCH或DELETE请求时,请确保您已从新文件更改SessionAuthentication为。SessionCsrfExemptAuthentication查看示例: @api_view(["POST"])\n @authentication_classes([SessionCsrfExemptAuthentication])\n @permission_classes([IsAuthenticated])\n def some_view(request) -> "Response":\n # some logic here\n return Response({})\nRun Code Online (Sandbox Code Playgroud)\n这个技巧允许你覆盖方法(pass),enforce_csrf并且新的会话身份验证类将跳过 CSRF 检查。
\xe2\x9c\x8c\xef\xb8\x8f
\n| 归档时间: |
|
| 查看次数: |
64809 次 |
| 最近记录: |