【问题标题】:Django DRF permissions on create related objectsDjango DRF 创建相关对象的权限
【发布时间】:2019-03-17 21:02:56
【问题描述】:

我努力在 Django REST 框架上强制执行对象创建的安全性。

基本上,我可以使用“has_object_permission”在对象级别强制执行安全性:登录用户必须是对象的所有者才能操作它。 实际上,如文档中所述,我缩小了查询集中的对象检索范围,所以我得到了 404 而不是 403。 我认为这不是问题(更好,因为它隐藏了对象的存在)

但我没有成功禁止其他用户创建相关对象....

我使用 ModelSerializer 和 ModelViewSet。

这里有一些幼稚的 sn-ps:

models.py:

class Daddy(models.Model):
    id = models.UUIDField(primary_key=True, default=uuid.uuid4, editable=False)
    name = models.CharField(max_length=20)
    owner = models.ForeignKey(settings.AUTH_USER_MODEL, on_delete=models.CASCADE)

class Kiddy(models.Model):
    title = models.CharField(max_length=12)
    daddy = models.foreignKey(Daddy, on_delete=models.CASCADE)

serializers.py:

class KiddySerializer(serializers.ModelSerializer):
    class Meta:
        model = Kiddy
        fields = '__all__'

viewsets.py:

class KiddyViewSet(viewsets.ModelViewSet):
    serializer_class = KiddySerializer
    queryset = User.objects.none()

    permission_classes = (IsAuthenticated, IsOwner, )

    def get_queryset(self):
        dad_uuid = self.kwargs['dad']
        return Kiddy.objects.filter(daddy__pk=dad_uuid).filter(daddy__owner=self.request.user)

router.py:

router = routers.DefaultRouter()
router.register(r'dad', KiddyViewSet, base_name='kid')

urls.py:

path('api/<uuid:cv>/', include(router.urls))

通过这些 url 访问对象: http://..../api/4ecddcdd-1c0a-4d0b-8254-b0c0d2607e6d/ ---> 列出所有孩子

http://..../api/4ecddcdd-1c0a-4d0b-8254-b0c0d2607e6d/1 ---> 对象孩子

其实我是因为使用uuid,所以得到了一些安全性,这很难猜到……

permissions.py:

class IsOwner(permissions.BasePermission):
"""
Object-level permission to only allow owners of an object to edit it.
Assumes the model instance has an `owner` attribute.
"""

def has_object_permission(self, request, view, obj):
    if request.user != obj.daddy.owner:
        return False
    else:
        return True

如果使用错误的所有者登录,我可以创建相关的 Kiddy 对象!

我想,我必须以“has_permission”类型实现此权限。 但我不知道如何访问那里的对象,因为参数是请求和视图......

在这里,他找到了解决方案。但这根本不是通用的,因为我需要每个相关对象的自定义权限......而且我得到了很多! Check permissions on a related object in Django REST Framework

有什么想法吗?

【问题讨论】:

    标签: django permissions django-rest-framework


    【解决方案1】:

    好的,我解决了这个问题:-)

    在 permissions.py 中,我怀疑我必须这样做,我添加了这个“has_permission”:

    class IsOwnerParent(permissions.BasePermission):
        def has_permission(self, request, view):
            daddy = Daddy.objects.get(pk=view.kwargs['dad'])
            return daddy.owner == request.user
    

    并将其添加到我的 ModelViewSet 类中:

    class KiddyViewSet(viewsets.ModelViewSet):
        serializer_class = KiddySerializer
        queryset = User.objects.none()
    
        permission_classes = (IsAuthenticated, IsOwner, IsOwnerParent)
    
        def get_queryset(self):
            dad_uuid = self.kwargs['dad']
            return Kiddy.objects.filter(daddy__pk=dad_uuid).filter(daddy__owner=self.request.user)
    

    所以,其实这里提供的解决方案Check permissions on a related object in Django REST Framework 确实有效。而且它实际上非常通用,因为我的许多对象都与“爸爸”对象相关。

    实际上,现在检索对象列表的行为看起来更“正常”:我得到 403 错误而不是 404。

    我认为这个用例很常见:用户只能创建与他们拥有的对象相关的对象,他们也只能更新和删除他们拥有的对象。

    但也许可以做得更好?

    【讨论】:

      猜你喜欢
      • 2022-09-23
      • 2021-02-14
      • 1970-01-01
      • 1970-01-01
      • 2016-06-23
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2019-07-29
      相关资源
      最近更新 更多