我正在这里寻求澄清。
我已经构建了一个连接到Django Rest Framework(DRF)的react应用。该应用程序是完全私有的,这意味着未经身份验证的任何人都无法做任何事情。为此,我使用了TokenAuthentication(现在,因为我认为SessionAuthentication会更安全)。
我正在努力理解这一点:
我找到了一种使之工作的方法:通过用@permission_classes((AllowAny, ))
装饰我的视图类,可以很好地工作。但是我对此不满意。
那为什么呢?
在我的设置文件中,我有:
REST_FRAMEWORK = {
'DEFAULT_AUTHENTICATION_CLASSES': (
'rest_framework.authentication.TokenAuthentication',
),
'DEFAULT_PERMISSION_CLASSES': (
'rest_framework.permissions.IsAuthenticated', )
}
在DRF文档(link)中说:
DELETE请求要求用户具有对模型的删除权限。
但是,我的用户是管理员,所以为什么需要显式添加此装饰器?
我在做什么错?这不是最好的方法。如果我使用外部API客户端(例如Postman-我使用Paw)进行请求,为什么在没有装饰器的情况下也能正常工作?
作为参考,是我的简化视图类:
@permission_classes((AllowAny, ))
class ObservationAPIView(APIView):
def delete(self, request, test_id, observation_id, format=None):
# see if my object exists
try:
obs_object_to_delete = Observation.objects.get(pk=observation_id)
test_obj = Test.objects.get(pk=test_id)
except ObjectDoesNotExist:
errormsg = {
'observation id': observation_id,
'test id': test_id,
'message': 'Cannot delete this object. Observation ID or test ID not found.'
}
return Response(errormsg, status=status.HTTP_404_NOT_FOUND)
# it exists, delete it
obs_object_to_delete.delete()
# return the test data (not the deleted object)
serializer = TestSerializer(test_obj, many=False)
return Response(serializer.data)
def patch(self, request, test_id, observation_id, format=None):
# there is also a PATCH function to allow for edits.
# This does work well without the decorator.
答案 0 :(得分:1)
为什么会这样?
由于您是全局添加的 DEFAULT_PERMISSION_CLASSES
,(在settings
中)DRF将在每个基于类的视图中使用该 。
如果要对特定视图使用额外的/自定义权限类,则可以在 permission_classes
属性的帮助下将其添加到视图类中,
class SampleView(APIView):
permission_classes = (MyCustomPermissionClass,)
....
对于您来说, 您需要override
特定方法的默认行为 。
那么,如何以DRF
的方式为默认方法覆盖默认权限类?
APIView
类一个称为 get_permissions()
的方法
class SampleView(APIView):
def get_permissions(self):
if self.request.method == 'DELETE':
return [permission() for permission in (AllowAny,)]
return super(SampleView, self).get_permissions()
# your code
答案 1 :(得分:0)
找到了!指向delete方法的url中没有结尾斜杠。
但DRF并未给出404错误或类似的内容,而是以401(未经授权)错误进行了响应。这使我寻找授权中的错误。
但是仍然对此感到困惑:通过设置@permission_classes((AllowAny,))装饰器,尾部的斜线对于我的前端在预检后继续运行似乎没有必要。没有装饰器(因此具有正确的权限),React不想在预检后继续。如果您在网址中添加斜杠,则一切正常。那么这是怎么回事? allowAny是否绕过CORS?而且CORS是否需要尾部斜杠?
如果有人能够解释我的这种行为,我将不胜感激。
感谢大家的光临!!
答案 2 :(得分:0)
由于其他原因,我也有类似的症状,
也许调试故事对其他人很有用。
GET,POST,PUT-工作正常,DELETE-不工作
如果没有将“ AllowAny”权限授予所有人。
在views.py中对请求进行调试发现了该问题
在最后一种情况下,request.user == AnonymousUser
和request.auth == none
。
原因是前端的DELETE请求的语法不正确
(在JS fetch(url, {method: "DELETE", headers, body})
中
选项的大括号位置错误),
造成标头和机体损失,公司。授权标头。