您自己的用户模型的 Django 每个对象权限

Posted

技术标签:

【中文标题】您自己的用户模型的 Django 每个对象权限【英文标题】:Django Per Object Permission for Your Own User Model 【发布时间】:2016-01-18 13:46:05 【问题描述】:

我已经实现了我自己的用户模型类,如下所示。请注意,它 不是 自定义 django 的 auth.User 模型。我是这个对象权限知识的新手,尤其是我的项目中需要的这个自定义用户模型。

您能否举一个在这种情况下添加每个对象权限的示例?

from django.contrib.auth.models import AbstractBaseUser, PermissionsMixin

class CustomUser(AbstractBaseUser, PermissionsMixin):
         email = models.EmailField(max_length=40, unique=True)
         #.... other fields are omitted

class Article(models.Model):
    title = models.CharField('title', max_length=120)
    body = models.TextField('body')
    author = models.ForeignKey(CustomUser)

现在,对象权限开始发挥作用。每个用户都可以创建/更新/删除/查看自己的文章对象,但只能查看其他人的文章,没有更新/删除的权限。

根据 Django 文档,模型级别的权限不适用于此处。如果文章被授予模型级别的更新权限,那么所有用户都可以更新其他人的文章。

我找到了 django-guardian。但是,这个自定义的 CustomUser 模型似乎没有希望了,因为它严重依赖 Django 的auth.User 模型!

https://django-guardian.readthedocs.org/en/v1.2/userguide/custom-user-model.html

    我的案例是继承 AbstractBaseUser 而不是 AbstractUser; 这不适用于管理员,仅适用于我的后端代码逻辑; 我这里没有使用 Django REST API,但是如果 REST API 合适,请举个例子。

【问题讨论】:

您是否正在使用 Django Rest Framework?还是只有 Django? 您希望将其集成到 Django 管理中,还是仅在您自己的代码中使用? 已在更新中回答。 【参考方案1】:

在你发的documentation page里,还写着:

基本上,如果我们继承 AbstractUser 或定义多对多关系 使用 auth.Group (并给出反向关联名称组)我们应该是 很好。

既然这是你正在做的事情,你应该按照Django documentention 中的说明设置AUTH_USER_MODEL(另请参阅the ticket 和commit code 以了解Django 1.5 的兼容性)。

【讨论】:

谢谢,但我的情况是 AbstractBaseUser 而不是 AbstractUser。它们是不同的。【参考方案2】:

即使使用标准的auth.User 模型,Django 也没有内置对象级权限。但基础在于 Django 的 PermissionsMixin 定义了 has_perm 方法,该方法接受模型实例。默认情况下,Django 什么都不做,但你可以。

has_perm 方法有效地将繁重的工作转移到已注册的身份验证后端。因此,您可以创建一个自定义身份验证后端,专门用于执行您的对象级权限检查。它不需要实际处理身份验证。它可以像基本类上的单个方法一样简单。您只需要以下内容(未经测试)即可:

class ObjectPermissionsBackend(object):

    def has_perm(self, user_obj, perm, obj=None):
        if not obj:
            return False # not dealing with non-object permissions

        if perm == 'view':
            return True # anyone can view
        elif obj.author_id == user_obj.pk:
            return True
        else:
            return False

通过 AUTHENTICATION_BACKENDS 设置告诉 Django 使用您的自定义后端。在settings.py中:

AUTHENTICATION_BACKENDS = ('django.contrib.auth.backends.ModelBackend', 'path.to.ObjectPermissionsBackend')

然后,在您的代码中:

if user.has_perm('edit', article_instance):
    # allow editing

见https://docs.djangoproject.com/en/1.8/topics/auth/customizing/#custom-users-and-permissions和https://docs.djangoproject.com/en/1.8/topics/auth/customizing/#specifying-authentication-backends

【讨论】:

感谢您的回答。我也在寻找一些做得很好的包。 在这种情况下,@schneck's answer 应该可以工作。我没有使用过 django-guardian,但您提供的链接似乎表明您可以将它与您自己的自定义 User 模型一起使用,它只是警告它需要多对多User 模型和 auth.Group 模型之间的关系。您已经在使用的 Django 的PermissionsMixin 定义了这种关系。您在尝试将 django-guardian 用于您的模型时是否看到特定错误? django-guardian 涉及创建对象并且难以使用。但它很强大,你有一个简单的例子吗?他们的示例项目没有公开太多功能。所以,我想出了一些其他的包来使用。 我没有使用 django-guardian 的示例,没有。正如您所说,它功能强大,但似乎确实涉及为每个对象分配权限 - 您示例中的每个文章。您可以使用 Django 信号在第一次保存文章时自动将文章权限分配给作者。但是 django-rules (正如您在回答中提到的那样)似乎更适合您的要求。【参考方案3】:

我最终使用基于逻辑的每个对象权限,这样它就不会改变我的数据库。 django-rules 支持我的基于类的视图。记住要覆盖redirect_field_name,否则,如果用户登录,您将最终出现重定向循环。

【讨论】:

【参考方案4】:

您需要了解一些有关权限如何工作的基础知识。在这里,它以一种新手可以理解的方式进行: 第一步是在模型中使用 Meta 并在模型定义“本身中添加该模型的权限。现在,当您在 django 中迁移时,django 会知道‘嘿!现在我必须考虑一个自定义权限。好吧,让我将此添加到自定义权限' 现在是第二步,您定义用户并给他与您在第一步模型中定义的完全相同的权限。 (如果你能理解这一点,djago-gurdia doc 对你来说似乎很清晰)任何方式,所以当用户登录并在你的代码中使用模型时,你可以检查(好的,虚拟地问 django嘿 django!你还记得我在这个模型上定义了一个权限。并且给了一个用户同样的权限。你能检查并告诉我登录的用户是否真的有这个权限')

【讨论】:

以上是关于您自己的用户模型的 Django 每个对象权限的主要内容,如果未能解决你的问题,请参考以下文章

使用 Django 和 django-guardian 对象权限的每个对象的组

Django在每个用户的UI中隐藏帖子(对象)而不影响主模型

Django:如何显示内联表单集中每个模型对象的表单错误

创建临时用户帐户 - Django

Django月度用户帐单记录

为后端的每个用户创建 Django User 对象