Please enable Javascript to view the contents

Django的权限控制

 ·  ☕ 4 分钟

1. Django内置权限管理

1.1 权限分类

  1. Permission
    用来定义用户User A对任务Task的权限。
  2. User
    如果User A 对Model B有权限,那么User A 对Mode B中的全部实例都有相应权限。User对象的user_permission 字段用于管理用户的权限。使用 assign_perm 给User分配权限。
  3. Group
    如果Group C 对Model B有权限,那么属于Group C的全部User对Model B 都具有相应权限。

1.2 配置和实现

  1. Permission

Django定义每个model后,默认都会添加该model的add, change和delete三个permission,自定义的permission可以在定义model时手动添加:

1
2
3
4
5
6
7
8
class Task(models.Model):
    ...
    class Meta:
        permissions = (
            ("view_task", "Can see available tasks"),
            ("change_task_status", "Can change the status of tasks"),
            ("close_task", "Can remove a task by setting its status as closed"),
        )

每个permission都是django.contrib.auth.Permission类型的实例,该类型包含三个字段name, codename 和 content_type,其中 content_type 反映了 permission 属于哪个 model,codename 如上面的 view_task,代码逻辑中检查权限时要用, name 是 permission 的描述,将permission 打印到屏幕或页面时默认显示的就是 name。

在 model 中创建自定义权限,从系统开发的角度,可理解为创建系统的内置权限,如果需求中涉及到用户使用系统时创建自定义权限,则要通过下面方法:

1
2
3
4
5
6
from myapp.models import Post
from django.contrib.auth.models import Permission
from django.contrib.contenttypes.models import ContentType

content_type = ContentType.objects.get_for_model(Post)
permission = Permission.objects.create(codename='can_publish', name='Can Publish Posts', content_type=content_type)
  1. User和Group

django的内置权限认证被绑定在 django.contrib.auth中,而auth中的Permission模型又依赖于contenttypes。

1
2
3
4
INSTALLED_APPS = (
    'django.contrib.auth'
    'django.contrib.contenttypes'
)
1
manage.py syncdb

就会在数据库中,建立如下几个表:

  • auth_group
  • auth_group_permissions
  • auth_permission
  • auth_user
  • auth_user_groups
  • auth_user_user_permissions

从表名上可以看到,auth_user 有两个外部对应关系,groups 和 user_permissions

1
manage.py  shell

上面的命令,能够让解释器加载Django项目中的settings文件,进入可以对项目中对象直接操作的模式。

1
2
3
4
>>> from django.contrib.auth.models import User
>>> A  = User.objects.create_user('name','[email protected]','password')
>>> A.groups = [group_list]
>>> A.user_permissions = [permission_list]

每个对象的groups和user_permissions都有三个用于修改权限的方法。

A.groups.[add|remove|clear()]
A.user_permissions.[add|remove|clear()]

1.3 使用

通常使用有两种方法,

  • 在View函数中通过调用has_perm()函数来检测。
    A/Group.has_perm(‘applabel.task’) 用于检查用户/组的权限。另外,A.get_all_permissions()列出用户的所有权限,A.get_group_permissions()列出用户所属组的权限。
  • 在View函数前使用装饰器。
    @permission_required(‘applabel.task’)

2. Django-guardian

以通常的多人博客系统为例,每篇博文就是一个对象。上述的Django内置权限控制方式,达不到对象级的控制能力。Django中没有提供对象级别的权限控制,但是在架构上留下了接口。django-guardian就是一个很流行的对象级权限控制组件。Object Permission是一种对象颗粒度上的权限机制,它允许为每个具体对象授权。如果把对象b的读写权限赋予User A ,那么User A只具有对对象b的读写权限,而不能对其他同类对象进行操作。

2.1 配置

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14

pip install django-guardian

INSTALLED_APPS = (
    'guardian',
)

AUTHENTICATION_BACKENDS = [
    'django.contrib.auth.backends.ModelBackend', # this is default
    'guardian.backends.ObjectPermissionBackend',
]
#如果要支持匿名用户AnoymousUser的Object级别的权限控制,要在settings中加入
#匿名用户权限控制
ANONYMOUS_USER_ID = -1
1
python manage syncdb

就会在数据库中,建立如下几个表:

  • guardian_groupobjectpermission
  • guardian_userobjectpermission

2.2 使用

  1. 权限的编辑

guardian.shortcuts.assign(perm, user_or_group, obj=None) 添加权限
guardian.shortcuts.remove_perm(perm,user_or_group=None, obj=None) 删除权限
guardian.shortcuts.get_perms(user_or_group,obj) 获取全部权限

  • perm,这个参数是一个字符串,代表一个许可,格式必须为 app.perm_codename 或者perm_codename 。但是如果第三个参数是None,则必须为 app.perm_codename 格式。因此建议还是统一使用 app.perm_codename 格式。注意app并不是app的全路径,而是最后一级的模块名。这一点和 INSTALL_APP 中的 app 全路径不同,如果你的 app module 不只一级的话,这地方一定要注意。
  • user_or_group,这个参数是一个User或者Group类型的对象。
  • obj,这个参数就是相关的对象了。改参数是可省略的,如果省略则赋予Model权限。
  1. 权限的检测
  • user.has_perm('app.view_task') #检测权限
  • ObjectPermissionChecker(request.user).has_perm('app.view_task', task)
  • guardian.decorators.permission_required()

3. 参考资料


微信公众号
作者
微信公众号