【问题标题】:Django - How can I prevent access to other users' objects?Django - 如何防止访问其他用户的对象?
【发布时间】:2018-04-27 19:55:37
【问题描述】:

假设我有这样的 URL users/{id}/objects 并且我被验证为 ID 等于 1 的用户。目前我可以访问 ID 等于 2、3 等的用户对象。有谁知道我怎么能防止这种情况发生?

class UserObject(GenericAPIView):

    permission_classes = [UserPermission]
    def get(self, request, user_id):

            try:
                object = Object.objects.filter(user=user_id)
            except Object.DoesNotExist:
                return Response(status=status.HTTP_404_NOT_FOUND)
            serializer = ObjectSerializer(object, many=True)
            return Response(serializer.data)


class UserPermission(permissions.BasePermission):

    def has_permission(self, request, view):
        if request.user and request.user.is_authenticated():
            return True
        return False

我是这样尝试的:

serializer_class = ObjectSerializer
permission_classes = [IsAuthenticated, ]

def get_queryset(self):
    return Object.objects.filter(owner=self.request.user)

def get(self, request, user_id):

        try:
            object = Object.objects.filter(user=user_id)
        except Object.DoesNotExist:
            return Response(status=status.HTTP_404_NOT_FOUND)
        serializer = ObjectSerializer(object, many=True)
        return Response(serializer.data)

【问题讨论】:

  • 在模板中检查id是否== request.user.id
  • 在视图中,而是。
  • @mohammedqudah 我用 if user_id == self.request.user.id: 尝试过,但它不起作用。也许可以在GetPermission Class 中查看?
  • @VincentBuscarello 不,只有所有者才能访问这些对象。目前只需要成为用户并经过身份验证,您就可以访问不同用户的所有对象。我想让它可以只访问自己的对象。
  • @VincentBuscarello 我在def has_permission(self, request, view): 下方添加了print("test"),在发送users/1/objects 后打印了test

标签: python django python-3.x django-rest-framework django-views


【解决方案1】:

如果您重载视图的get_queryset 以仅返回属于当前用户的对象,那么 Django 将自行处理相应的错误和响应。例如,

class MyView(GenericAPIView):

    serializer_class = serializers.MySerializer
    permission_classes = (IsAuthenticated,)

    def get_queryset(self):
        return MyModel.objects.filter(owner=self.request.user)

另见http://www.django-rest-framework.org/api-guide/generic-views/#attributes

【讨论】:

  • 它不起作用。我将我的代码添加到更新的问题中。也许我做错了什么?
  • 它可能由于多种原因无法正常工作,例如您没有正确的身份验证类。或者owner 不是Portfolios 与Users 的链接方式。 owner 这个词没有什么神奇之处——您必须更改示例过滤器以适应您自己的关系情况。
  • 另外,如果你这样做,你可能不需要重载get - 重点是你可以通过这个来实现你的目标并且不需要为每个视图重载get
【解决方案2】:

您可以使用IsAuthenticated 权限仅检查某人是否已登录,而不是检查“手动”用户是否要求提供自己的数据。像这样:

class UserObject(GenericAPIView):

    permission_classes = (IsAuthenticated,)
    def get(self, request, user_id):

        if (str(reques.user.id) != user_id):
            return Response(status=status.HTTP_403_FORBIDDEN)

        try:
            object = Object.objects.filter(user=user_id)
        except Object.DoesNotExist:
            return Response(status=status.HTTP_404_NOT_FOUND)

        serializer = ObjectSerializer(object, many=True)
        return Response(serializer.data)

如果您真的想使用自定义权限,您可以保持视图不变并使您的权限类别如下:

class UserPermission(permissions.BasePermission):

    def has_permission(self, request, view):
        if (not request.user.is_authenticated()):
            return False

        user_id = request.path.split('/')[1]

        if (str(request.user.id) == user_id):
            return True

        return False

注意:我推荐第一个选项。

注意:此代码是一个示例,如果不能立即运行,请尝试 理解这个想法并适应它。我没有测试它,它可能需要一些调整,特别是从response.path 获得user_id 的部分。

【讨论】:

  • 但也许可以将它添加到 UserPermission 类中?如果我使用您的解决方案,我将有很多 GenericViews 需要修改。
  • 我认为你可以做到,虽然它有点棘手。您需要从自定义权限类中的has_permission 函数访问user_id。由于request 对象是HttpRequestextension,其中haspath 字段,您可以从那里提取user_id 并将其与request.user.id 进行比较,并使其在不影响您的视图的情况下工作.
  • 你能告诉我如何在class UserPermission上完成吗?
  • 编辑了答案。
  • 只需将 1 更改为 2
猜你喜欢
  • 2013-12-04
  • 2020-05-21
  • 2015-10-23
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多