【问题标题】:Django Per Object Permission for Your Own User Model您自己的用户模型的 Django 每个对象权限
【发布时间】: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

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

【问题讨论】:

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

标签: django permissions


【解决方案1】:

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

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

既然这是你正在做的事情,你应该按照Django documentention 中的说明设置AUTH_USER_MODEL(另请参阅the ticketcommit 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-permissionshttps://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!你还记得我在这个模型上定义了一个权限。并且给了一个用户同样的权限。你能检查并告诉我登录的用户是否真的有这个权限')

    【讨论】:

      猜你喜欢
      • 2021-02-22
      • 1970-01-01
      • 2014-06-21
      • 2021-12-21
      • 2015-08-27
      • 2016-07-31
      • 2019-08-17
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多