Django Rest Framework 源码解析--权限

Django Rest Framework 源码解析--权限

接上一篇文章;restframework重写的dispatch()方法中,执行了inital()函数。inital()中check_permissions(request) 方法实现了请求的鉴权、权限控制功能。
1、check_permissions(request)函数中,循环了权限类的对象列表,依次执行权限对象的 has_permission() 方法

  • 如果有权限,则继续循环使用下一个权限对象再来检查request

  • 如果没有权限,执行permission_denied()函数,抛出异常(通过权限对象的message变量来自定义异常信息

def check_permissions(self, request):
    """
    Check if the request should be permitted.
    Raises an appropriate exception if the request is not permitted.
    
    检查请求是否被权限限制。
    如果请求没有权限,抛出对应的异常
    """
    for permission in self.get_permissions():
        if not permission.has_permission(request, self):
            self.permission_denied(
                request, message=getattr(permission, 'message', None)
            )

2、get_permissions()方法找到setting中指定的权限类,或者在View中重写的权限类

def get_permissions(self):
    """
    Instantiates and returns the list of permissions that this view requires.
    """
    # 列表推导式,来生成权限类的列表
    return [permission() for permission in self.permission_classes]

3、如果没有权限,执行permission_denied()函数,抛出异常(通过权限对象的message变量来自定义异常信息)

def permission_denied(self, request, message=None):
    """
    If request is not permitted, determine what kind of exception to raise.
    """
    if request.authenticators and not request.successful_authenticator:
        raise exceptions.NotAuthenticated()
    # 抛出PermissionDenied(detail=message)异常,出入权限对象的message变量
    raise exceptions.PermissionDenied(detail=message)

使用示例:

1、自定义的权限类继 承BasePermission

  • 在重写 has_permission() 方法时,需要引入 request, view 参数,可以根据 request, view 来做权限控制

  • 在重写 has_object_permission() 方法时, 需要引入 request, view, obj 参数,可以根据 request, view, obj 来做权限控制

@six.add_metaclass(BasePermissionMetaclass)
class BasePermission(object):
    """
    A base class from which all permission classes should inherit.
    """
 
    def has_permission(self, request, view):
        """
        Return `True` if permission is granted, `False` otherwise.
        """
        return True
 
    def has_object_permission(self, request, view, obj):
        """
        Return `True` if permission is granted, `False` otherwise.
        """
        return True

自定义权限类,示例:

class MyPermission(BasePermission):
    """
    自定义权限
    """
    message = "无权访问!"
    @classmethod
    def get_permission_from_role(self, request):
        try:
            perms = request.user.roles.values(
                'permissions__method',
            ).distinct()
            return [p['permissions__method'] for p in perms]
        except AttributeError:
            return None
 
    def has_permission(self, request, view):
        perms = self.get_permission_from_role(request)
        if perms:
            if 'admin' in perms:
                return True
            elif not hasattr(view, 'perms_map'):
                return True
            else:
                perms_map = view.perms_map
                _method = request._request.method.lower()
                for i in perms_map:
                    for method, alias in i.items():
                        if (_method == method or method == '*') and alias in perms:
                            return True

2、在View中重写permission_classes权限类列表,列表中几个权限类表示要经过几层权限检查(从左至右依次检查)

class TestView(APIView):
    # 自定义方法权限映射
    perms_map = ({'*': 'admin'}, {'*': 'test_all'}, {'post': 'test_copy'})
    # 在View中重写permission_classes权限类列表,几个类表示要经过几层权限检查
    permission_classes = (MyPermission,)
    def post(self, request, format=None):
        pass

3、或者在全局setting.py中指定权限类的路径,对全站的View进行默认的权限检查

REST_FRAMEWORK = {
    "DEFAULT_PERMISSION_CLASSES": ('restframework.permissions.MyPermission',)
}

你可能感兴趣的:(Django Rest Framework 源码解析--权限)