DRF中的DELETE请求需要AllowAny权限吗​​?

时间:2018-10-31 18:36:44

标签: django reactjs authentication django-rest-framework token

我正在这里寻求澄清。

我已经构建了一个连接到Django Rest Framework(DRF)的react应用。该应用程序是完全私有的,这意味着未经身份验证的任何人都无法做任何事情。为此,我使用了TokenAuthentication(现在,因为我认为SessionAuthentication会更安全)。

我正在努力理解这一点:

  • 我可以使用自己的令牌进行身份验证并设置适当的标头(授权)。
  • 我可以毫无问题地执行GET / POST / PATCH请求
  • 但是:DELETE请求不起作用:我收到401-未经授权的错误。但是带有令牌的标头就可以了。我正在使用DELETE请求从数据库中删除对象。

我找到了一种使之工作的方法:通过用@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.

3 个答案:

答案 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 == AnonymousUserrequest.auth == none

原因是前端的DELETE请求的语法不正确
(在JS fetch(url, {method: "DELETE", headers, body})
中 选项的大括号位置错误),
造成标头和机体损失,公司。授权标头。