Django REST框架忽略has_object_permission

nzkunb0c  于 2023-08-08  发布在  Go
关注(0)|答案(2)|浏览(96)

我正在尝试限制用户对对象的访问。只有创建者才能修改对象。就像我写的教程里说的那样

class IsOwnerOrReadOnly(permissions.BasePermission):
    def has_object_permission(self, request, view, obj):
        return False

字符串
并将其添加到permission_classes中。但是任何用户仍然可以修改任何对象。如果我加上方法

def has_permission(self, request, view):
        return False


没人能做什么所以所有的行为都是由唯一的has_permission方法控制的,该方法没有提供任何处理每个对象权限的方法。我做错什么了吗?下面是请求处理器的代码

class ProblemsHandler(APIView):

    permission_classes = (
        IsOwnerOrReadOnly,
        permissions.IsAuthenticatedOrReadOnly,
    )

    def pre_save(self, request, problem):
        problem.author = request.user

    def get_object(self, request, pk, format):
        try:
            problem = ProblemsModel.objects.get(pk=pk)
            serializer = ProblemsSerializer(problem)
            return Response(serializer.data, status=HTTP_200_OK)
        except ProblemsModel.DoesNotExist:
            raise Http404

    def get_list(self, request, format):
        problems = ProblemsModel.objects.all()
        serializer = ProblemsSerializer(problems, many=True)
        return Response(serializer.data, status=HTTP_200_OK)

    def get(self, request, pk=None, format=None):
        if pk:
            return self.get_object(request, pk, format)
        else:
            return self.get_list(request, format)

    def post(self, request, format=None):
        serializer = ProblemsSerializer(data=request.DATA)
        if serializer.is_valid():
            self.pre_save(request, serializer.object)
            serializer.save()
            return Response(serializer.data, status=HTTP_201_CREATED)
        else:
            return Response(serializer.errors, status=HTTP_400_BAD_REQUEST)

    def put(self, request, pk, format=None):
        try:
            problem = ProblemsModel.objects.get(pk=pk)
            serializer = ProblemsSerializer(problem, data=request.DATA)
            if serializer.is_valid():
                self.pre_save(request, serializer.object)
                serializer.save()
                return Response(serializer.data, status=HTTP_200_OK)
            else:
                return Response(serializer.errors, status=HTTP_400_BAD_REQUEST)
        except ProblemsModel.DoesNotExist:
            raise Http404

    def delete(self, request, pk, format=None):
        try:
            problem = ProblemsModel.objects.get(pk=pk)
            problem.delete()
            return Response(status=HTTP_204_NO_CONTENT)
        except ProblemsModel.DoesNotExist:
            raise Http404

k4ymrczo

k4ymrczo1#

对象的许可检查由DRF在方法APIView.check_object_permissions中完成。
由于您没有使用GenericAPIView,因此您定义了自己的get_object方法,并且必须自己调用check_object_permissions。由于您有点误用get_object,因此必须检查GET(single)、PUT和DELETE

self.check_object_permissions(self.request, obj)

字符串
也许可以更好地了解DRF Generic Views,因为您的用例看起来很像它们。通常情况下,get_object应该只返回一个对象并检查权限。

xiozqbni

xiozqbni2#

我将分享我的视图集解决方案。我希望超级用户有权限的所有,但对于工作人员,只有访问自己的详细信息
这是如何使用权限(对于get单个对象调用)
我的设置:Django 4,python 3.11
我的API类:

class StaffViewSet(viewsets.ModelViewSet):
    serializer_class = StaffSerializer
    queryset = user.objects.filter(is_staff=True)

    def get_permissions(self):
        """
        Instantiates and returns the list of permissions that this view requires.
        """
        if self.action in ["list", "create", "delete"]:
            permission_classes = [LoggedInSuperUser]
        else:
            permission_classes = [LoggedInSuperUser|LoggedInStaff]
        return [permission() for permission in permission_classes]

字符串
我的权限类:

class LoggedInStaff(BasePermission):
    def has_permission(self, request, view):
        return all([request.user.is_staff, request.user.is_authenticated])

    def has_object_permission(self, request, view, obj):
        if obj.email == request.user.email:
            return True
        return False

class LoggedInSuperUser(BasePermission):
    def has_permission(self, request, view):
        return all([request.user.is_superuser, request.user.is_authenticated])

    def has_object_permission(self, request, view, obj):
        return all([request.user.is_superuser, request.user.is_authenticated])

相关问题