您自己的用户模型的 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 对象权限的每个对象的组