七、权限

一、权限源码

    def check_permissions(self, request):
		
        # 获取权限组件中的权限对象
        for permission in self.get_permissions():
            
            '''
            1. 由此看出,权限对象必须存在has_permission方法
            2. 此处的request为加工后的request对象,self为当前视图类
            3. 必须存在一个返回值,且有可能是bool值,有权限返回True,无权限返回False
            '''
            if not permission.has_permission(request, self):
                # 权限不通过,则执行以下permission_denied方法
                self.permission_denied(
                    request,
                    message=getattr(permission, 'message', None),
                    code=getattr(permission, 'code', None)
                )
       
    # 返回权限组件实例化对象
    def get_permissions(self):
        # 和认证组件内部一样的作用,获取permission_classes列表中的权限组件,并实例化
        return [permission() for permission in self.permission_classes]
    
    
	# permission_classes需要是一个列表
    permission_classes = api_settings.DEFAULT_PERMISSION_CLASSES  

二、drf权限类

from rest_framework.permissions import 

1、AllowAny

全部允许

class AllowAny(BasePermission):
    
    def has_permission(self, request, view):
        return True

2、AND

class AND:
    def __init__(self, op1, op2):
        self.op1 = op1
        self.op2 = op2

    def has_permission(self, request, view):
        return (
            self.op1.has_permission(request, view) and
            self.op2.has_permission(request, view)
        )

    def has_object_permission(self, request, view, obj):
        return (
            self.op1.has_object_permission(request, view, obj) and
            self.op2.has_object_permission(request, view, obj)
        )

3、BasePermission

全部允许

class BasePermission(metaclass=BasePermissionMetaclass):

    def has_permission(self, request, view):
        return True

    def has_object_permission(self, request, view, obj):
        return True

4、BasePermissionMetaclass

class BasePermissionMetaclass(OperationHolderMixin, type):
    pass

5、DjangoModelPermissions

class DjangoModelPermissions(BasePermission):

    perms_map = {
        'GET': [],
        'OPTIONS': [],
        'HEAD': [],
        'POST': ['%(app_label)s.add_%(model_name)s'],
        'PUT': ['%(app_label)s.change_%(model_name)s'],
        'PATCH': ['%(app_label)s.change_%(model_name)s'],
        'DELETE': ['%(app_label)s.delete_%(model_name)s'],
    }

    authenticated_users_only = True

    def get_required_permissions(self, method, model_cls):
  
        kwargs = {
            'app_label': model_cls._meta.app_label,
            'model_name': model_cls._meta.model_name
        }

        if method not in self.perms_map:
            raise exceptions.MethodNotAllowed(method)

        return [perm % kwargs for perm in self.perms_map[method]]

    def _queryset(self, view):
        assert hasattr(view, 'get_queryset') \
            or getattr(view, 'queryset', None) is not None, (
            'Cannot apply {} on a view that does not set '
            '`.queryset` or have a `.get_queryset()` method.'
        ).format(self.__class__.__name__)

        if hasattr(view, 'get_queryset'):
            queryset = view.get_queryset()
            assert queryset is not None, (
                '{}.get_queryset() returned None'.format(view.__class__.__name__)
            )
            return queryset
        return view.queryset

    def has_permission(self, request, view):

        if getattr(view, '_ignore_model_permissions', False):
            return True

        if not request.user or (
           not request.user.is_authenticated and self.authenticated_users_only):
            return False

        queryset = self._queryset(view)
        perms = self.get_required_permissions(request.method, queryset.model)

        return request.user.has_perms(perms)

6、DjangoModelPermissionsOrAnonReadOnly

class DjangoModelPermissionsOrAnonReadOnly(DjangoModelPermissions):

    authenticated_users_only = False

7、DjangoObjectPermissions

class DjangoObjectPermissions(DjangoModelPermissions):

    perms_map = {
        'GET': [],
        'OPTIONS': [],
        'HEAD': [],
        'POST': ['%(app_label)s.add_%(model_name)s'],
        'PUT': ['%(app_label)s.change_%(model_name)s'],
        'PATCH': ['%(app_label)s.change_%(model_name)s'],
        'DELETE': ['%(app_label)s.delete_%(model_name)s'],
    }

    def get_required_object_permissions(self, method, model_cls):
        kwargs = {
            'app_label': model_cls._meta.app_label,
            'model_name': model_cls._meta.model_name
        }

        if method not in self.perms_map:
            raise exceptions.MethodNotAllowed(method)

        return [perm % kwargs for perm in self.perms_map[method]]

    def has_object_permission(self, request, view, obj):
        
        queryset = self._queryset(view)
        model_cls = queryset.model
        user = request.user

        perms = self.get_required_object_permissions(request.method, model_cls)

        if not user.has_perms(perms, obj):
            
            if request.method in SAFE_METHODS:
                raise Http404

            read_perms = self.get_required_object_permissions('GET', model_cls)
            if not user.has_perms(read_perms, obj):
                raise Http404

            # Has read permissions.
            return False

        return True

8、IsAdminUser

超级管理员

class IsAdminUser(BasePermission):

    def has_permission(self, request, view):
        return bool(request.user and request.user.is_staff)

9、IsAuthenticated

普通用户 and 超级管理员

class IsAuthenticated(BasePermission):

    def has_permission(self, request, view):
        return bool(request.user and request.user.is_authenticated)

10、IsAuthenticatedOrReadOnly

普通用户 and 超级管理员 or 请求方式('GET', 'HEAD', 'OPTIONS')

SAFE_METHODS = ('GET', 'HEAD', 'OPTIONS')

class IsAuthenticatedOrReadOnly(BasePermission):

    def has_permission(self, request, view):
        return bool(
            request.method in SAFE_METHODS or
            request.user and
            request.user.is_authenticated
        )

11、NOT

调用其他权限类,并将值取反

class NOT:
    def __init__(self, op1):
        self.op1 = op1

    def has_permission(self, request, view):
        return not self.op1.has_permission(request, view)

    def has_object_permission(self, request, view, obj):
        return not self.op1.has_object_permission(request, view, obj)

12、OperandHolder

class OperandHolder(OperationHolderMixin):
    def __init__(self, operator_class, op1_class, op2_class):
        self.operator_class = operator_class
        self.op1_class = op1_class
        self.op2_class = op2_class

    def __call__(self, *args, **kwargs):
        op1 = self.op1_class(*args, **kwargs)
        op2 = self.op2_class(*args, **kwargs)
        return self.operator_class(op1, op2)

13、OperationHolderMixin

class OperationHolderMixin:
    def __and__(self, other):
        return OperandHolder(AND, self, other)

    def __or__(self, other):
        return OperandHolder(OR, self, other)

    def __rand__(self, other):
        return OperandHolder(AND, other, self)

    def __ror__(self, other):
        return OperandHolder(OR, other, self)

    def __invert__(self):
        return SingleOperandHolder(NOT, self)

14、OR

class OR:
    def __init__(self, op1, op2):
        self.op1 = op1
        self.op2 = op2

    def has_permission(self, request, view):
        return (
            self.op1.has_permission(request, view) or
            self.op2.has_permission(request, view)
        )

    def has_object_permission(self, request, view, obj):
        return (
            self.op1.has_object_permission(request, view, obj) or
            self.op2.has_object_permission(request, view, obj)
        )

15、SingleOperandHolder

class SingleOperandHolder(OperationHolderMixin):
    def __init__(self, operator_class, op1_class):
        self.operator_class = operator_class
        self.op1_class = op1_class

    def __call__(self, *args, **kwargs):
        op1 = self.op1_class(*args, **kwargs)
        return self.operator_class(op1)

三、权限配置

from rest_framework import settings

# 全局配置-settings.py
REMOVED_SETTINGS = [
    # 认证组件配置
    "DEFAULT_AUTHENTICATION_CLASSES":[
        "app01.认证类路径",
        ...
    ],
    
    # 权限组件配置
    'DEFAULT_PERMISSION_CLASSES': [
        'app01.权限类路径',
        ...
    ],
]


# 局部配置,在视图类中写
permission_classes=[
    '认证类',
    ...
]

# 局部禁用,在视图类中写
permission_classes=[]
上一篇:SpringBoot学习项目-博客系统-part9


下一篇:软件设计——代理模式之婚介所