我创建了一个Django(1.10.3)项目,其中包含一个继承自AbstractBaseUser
的自定义用户模型。在开发这个东西的几个星期后,我发现我需要为管理员用户提供更细粒度的权限,因此我使用PermissionsMixin
扩展了我的用户模型,生成并应用了迁移,并更新了我的ModelAdmin
。
要尝试一下,我使用我的超级用户登录管理员,并创建了一个手动添加了所有权限的新用户。当我使用该新用户登录时,我受到了很好的"您没有权限编辑任何内容" 。
所以我去了shell,检查了用户的权限,他们就在那里。
>>> u = User.objects.get(username='new_user')
>>> u.get_all_permissions()
{'admin.add_logentry', ...}
然而,
>>> u.has_perm('admin.add_logentry')
False
现在,如果用户不是活跃的超级用户,has_perm
的作用就是调用它:
def _user_has_perm(user, perm, obj):
for backend in auth.get_backends():
if not hasattr(backend, 'has_perm'):
continue
try:
if backend.has_perm(user, perm, obj):
return True
except PermissionDenied:
return False
return False
但是,
>>> from django.contrib.auth import get_backends
>>> backend = get_backends()[0] # django.contrib.auth.backends.ModelBackend
>>> backend.has_perm(u, 'admin.add_logentry')
True
所以,
为什么user.has_perm(perm)
和backend.has_perm(user, perm)
会返回不同的值?
最后,如何在这种情况下让权限系统正常工作?
答案 0 :(得分:1)
我应该对这个问题的实际答案感到羞耻。至少我希望从中吸取教训。也许我可以按照“总是先检查你自己的实现”的方式添加一些东西来修复启发式错误。
这两种方法显然不可能返回不同的东西,这使我检查我是否真的在调用它们。事实证明,我完全忘记了我自己的has_perm
实现,我为了让用户模型与管理员兼容而心不在焉。
当然,此实现仅检查超级用户状态。
我认为奥卡姆的家伙正在做点什么。