为何DjangoObjectPermissions对管理员用户不生效?
问题描述
我配置了DjangoObjectPermissions,该权限对普通用户完全生效,但对管理员用户无效。
models.py
class Transformer(models.Model): name = models.CharField(max_length=150, unique=True) alternate_mode = models.CharField( max_length=250, blank=True, null=True) description = models.CharField( max_length=500, blank=True, null=True) alive = models.BooleanField(default=False) class Meta: ordering = ('name',) def __str__(self): return self.name
serializers.py
class TransformerSerializer(serializers.ModelSerializer): class Meta: model = Transformer fields = "__all__"
views.py
class TransformerList(generics.ListCreateAPIView): queryset = Transformer.objects.all() serializer_class = TransformerSerializer permission_classes = [DjangoObjectPermissions, ] def perform_create(self, serializer): instance = serializer.save() assign_perm("delete_transformer", self.request.user, instance) class TransformerDetail(generics.RetrieveUpdateDestroyAPIView): queryset = Transformer.objects.all() serializer_class = TransformerSerializer permission_classes = [DjangoObjectPermissions, ]
settings.py
INSTALLED_APPS = [ 'django.contrib.admin', 'django.contrib.auth', 'django.contrib.contenttypes', 'django.contrib.sessions', 'django.contrib.messages', 'django.contrib.staticfiles', 'rest_framework', 'snippets', 'class_based_api_views', 'guardian' ] AUTHENTICATION_BACKENDS = ( 'django.contrib.auth.backends.ModelBackend', 'guardian.backends.ObjectPermissionBackend', )
测试情况
- 创建管理员用户(用户名:admin)
- 创建普通用户(用户名:user3)
用user3创建一条Transformer记录后:
- 对象权限显示仅
user3拥有该记录的删除权限 user3可删除自己创建的记录,符合预期- 管理员无需配置任何对象权限,即可对该记录执行编辑/删除操作,不符合预期
问题
为何管理员用户在没有对应权限的情况下仍能编辑/删除对象?
解答
这是因为Django的超级用户(管理员)默认拥有is_superuser属性,而DRF的DjangoObjectPermissions权限类会直接放行超级用户的所有操作。
DjangoObjectPermissions继承自DjangoModelPermissions,后者的源码逻辑中明确:只要用户是超级用户(request.user.is_superuser为True),权限验证会直接返回通过,不会再检查具体的对象权限。
要解决这个问题,你需要自定义一个权限类,移除超级用户的默认放行逻辑,强制校验对象权限:
# 可放在views.py或单独的permissions.py文件中 from rest_framework.permissions import DjangoObjectPermissions class StrictDjangoObjectPermissions(DjangoObjectPermissions): def has_permission(self, request, view): # 跳过超级用户直接通过的逻辑,仅执行基础权限检查 return super(DjangoObjectPermissions, self).has_permission(request, view) def has_object_permission(self, request, view, obj): # 强制执行对象权限校验,不判断用户是否为超级用户 return super().has_object_permission(request, view, obj)
之后在视图中替换原有的权限类:
class TransformerList(generics.ListCreateAPIView): # 保留其他配置 permission_classes = [StrictDjangoObjectPermissions, ] class TransformerDetail(generics.RetrieveUpdateDestroyAPIView): # 保留其他配置 permission_classes = [StrictDjangoObjectPermissions, ]
这种方式直接可控,也可以通过修改guardian的全局配置限制超级用户,但自定义权限类的方案更灵活。
内容的提问来源于stack exchange,提问作者Parth
相关产品推荐
相关产品推荐

