Django DRF创建相关对象的权限 [英] Django DRF permissions on create related objects
问题描述
我很难在Django REST框架上强制执行对象创建上的安全性.
I struggle to enforce security on objects creation on Django REST framework.
基本上,我可以使用"has_object_permission"在对象级别实施安全性:登录的用户必须是该对象的所有者才能进行操作. 实际上,正如文档中所述,我缩小了查询集中的对象检索范围,因此得到了404而不是403. 我认为这不是问题(甚至更好,因为它隐藏了对象的存在)
Basically, I can enforce security at the object level with 'has_object_permission' : the logged in user must be the owner of the object to manipulate it. Actually, as stated in the doc, I narrow objects retrieval in the queryset so, i got 404 instead of 403. That I think is not a problem (even better, as it hides the objects existences)
但是我未能成功地禁止另一个用户创建相关对象....
我使用ModelSerializer和ModelViewSet.
I use ModelSerializer and ModelViewSet.
这是一些天真的片段:
models.py:
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:
serializers.py :
class KiddySerializer(serializers.ModelSerializer):
class Meta:
model = Kiddy
fields = '__all__'
viewsets.py:
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.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/ --->列出所有孩子
Objects are accessed with those urls : http://..../api/4ecddcdd-1c0a-4d0b-8254-b0c0d2607e6d/ ---> list all kids
http://..../api/4ecddcdd -1c0a-4d0b-8254-b0c0d2607e6d/1 --->对象小子
实际上,因为使用uuid,所以我得到了一些安全保障,这很难猜到...
Actually, I got some security because I use uuid, and this is hard to guess...
permissions.py:
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对象!
If logged with the wrong owner, I can create related kiddy objects!
我想,我必须以"has_permission"类型实现此权限. 但是我不知道如何访问那里的对象,因为参数是请求和查看...
I guess, I have to implement this permission in a 'has_permission' type. But I do not know how to access object in there as params are request and view...
在这里,他找到了解决方案.但这根本不是通用的,因为我将需要对每个相关对象的自定义权限...我得到了很多!!! 在Django REST Framework中检查对相关对象的权限
Here, he found a solution. But this is not generic at all, cause I'll need a custom permission for every related objects... and I got many!!! Check permissions on a related object in Django REST Framework
有什么主意吗?
推荐答案
好的,我解决了这个问题:-)
OK, I solved this issue :-)
正如我怀疑的那样,在Permissions.py中,我添加了这个"has_permission":
In permissions.py, as I suspected I'll have to, I added this '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类中:
and added it in my ModelViewSet class :
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)
因此,实际上,此处提供的解决方案检查Django REST Framework中相关对象的权限 做过.而且实际上很通用,因为我的许多对象都与爸爸"对象有关.
So, in fact the solution provided here Check permissions on a related object in Django REST Framework did work. And it's actually quite generic as many of my objects are related to the 'Daddy' objects.
实际上,现在检索对象列表的行为看起来更正常":我收到403错误而不是404错误.
Actually, now the behavior in retrieving a list of objects looks more 'normal' : I got 403 errors instead of 404.
我认为这种用例非常普遍:用户只能创建与其拥有的对象相关的对象,并且也只能更新和删除其拥有的对象.
I think this use case is quite common : users can only create related objects to objects they own and they can only update and delete objects they own too.
但是也许可以做一个更好的方法?
But maybe it can be done a better way?
这篇关于Django DRF创建相关对象的权限的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!