跳转至

Django权限机制

Model Permissions

​ Django原生权限机制基于Model实现,对于每个Model而言,系统将自动添加add、change和delete这三个权限。

自定义的权限需要在model中手动添加:

class Token(models.Model):
    class Meta:
        permissions = (
            ("view_token", "Can see token"),
        )

每个权限包含

  • content_type 对应该权限作用的模型,既Token。
  • code_name 对应该权限功能,既view_token,在检查权限时会使用。
  • name 对应该权限功能的描述,既Can see token。

自定义权限使用代码新建:

from django.contrib.auth.models import Permission
from django.contrib.contenttypes.models import ContentType
content_type = ContentType.objects.get_for_model(Token)
permission = Permission.objects.create(codename='view_token',
                                       name='Can see token',
                                       content_type=content_type)
print(request.user.has_perm('user.add_token'))  # 检查用户是否拥有某项权限 has_perm(app_name.permission_codename)
permission = Permission.objects.get(codename='add_token')  # 获取权限实例
request.user.user_permissions.add(permission)  # 为用户新增权限

print(request.user.get_all_permissions())  # 查看用户全部权限

# 由于权限缓存机制 用户的权限在第一次获取用户实例时会被缓存下来
# 为用户增加了权限后不会立即更新 若想立即查询用户的新的权限状态
# 需要重新获取用户实例 详见:djangoproject-permission-caching
user = User.objects.get(pk=request.user.id)
print(user.has_perm('user.add_token'))  # 立即检查新权限添加状态

user.user_permissions.remove(permission)  # 为用户删除权限
request.user.user_permissions.clear()  # 清除用户全部权限

http://blog.igevin.info/posts/django-permission/

https://docs.djangoproject.com/en/1.10/ref/contrib/auth/

Group Permission

Group Permission的管理机制基本上和Moedl Permission一直,基本方法如下:

group.permissions.set([permission_list])
group.permissions.add(permission, permission, ...)
group.permissions.remove(permission, permission, ...)
group.permissions.clear()

权限检查依旧使用model.has_permission()方法。

new_group, created = Group.objects.get_or_create(name='new_group')
new_group.permissions.add(permission)
request.user.groups.add(new_group)

DRF中自定义权限检查

# override GET /user/
# 查看用户列表
def list(self, request, *args, **kwargs):
    permission_required(request.user, ['user.view_user'])
    users = User.objects.all()
    serializer = UserListSerializer(users, many=True)
    return Response(serializer.data)
from rest_framework.exceptions import PermissionDenied, MethodNotAllowed

from .models import *


# 获取某个model的全部权限列表
# Receive ----------------------------------
# model: a model
# Return -----------------------------------
# permissions: all permission related to this model
def get_model_permission(model):
    content_type = ContentType.objects.get_for_model(model)
    permissions = Permission.objects.filter(content_type=content_type)
    return permissions

def permission_required(user, perm_list):
    if user.has_perms(perm_list):
        pass
    else:
        raise PermissionDenied
def list(self, request, *args, **kwargs):
    self.add_log(request=request)
    permission_list = []
    import django.apps
    for model in django.apps.apps.get_models():  # 获取所有的model
        data = {}
        content_type = ContentType.objects.get_for_model(model)  # 获取model对应的content_type
        permissions = Permission.objects.filter(content_type=content_type)  # 获取该model的所有permission
        serializer = self.get_serializer(permissions, many=True)  # 序列化
         data['name'] = str(model._meta.verbose_name)  # 压入json中
         data['content_type'] = str(content_type.id)
        data['permissions'] = serializer.data
        permission_list.append(data)  # json压入list中
    # 将list按照json中的content_type正序排列
    # 不加int(x['content_type])将按照str类型排序 顺序:1 10 11... 2 20
    # reverse 反序
    permission_list = sorted(permission_list, key=lambda x: int(x['content_type']), reverse=False)
    return success_response(permission_list)
from rest_framework.permissions import IsAdminUser

class IsVbAdminUser(IsAdminUser):
    """
    Allows access only to admin users.
    """
    def has_object_permission(self, request, view, obj):
        """
        Return `True` if permission is granted, `False` otherwise.
        """
        return self.has_permission(request, view)

然后在 viewset 中,例如获取详情接口,这样用,

@wrap_permission(IsVbAdminUser)
def retrieve(self, request, *args, **kwargs):

superuser在所有权限检测has_perm均返回True