首页 > 技术文章 > drf(三)—权限控制

Blogwj123 2022-04-07 08:27 原文

drf(三)—权限控制

问题引出:有些功能(数据)是需要具备一定权限的的用户才能进行访问,例如:VIP才有查看某些数据的功能。

上节内容的补充:

  • def _authenticate(self):
        for authenticator in self.authenticators: #循环配置文件中的列表认证
            try:
                user_auth_tuple = authenticator.authenticate(self)
            except exceptions.APIException:
                self._not_authenticated()
                raise # 抛出错误
    
            if user_auth_tuple is not None:
                self._authenticator = authenticator
                self.user, self.auth = user_auth_tuple
                return # 函数终止,对象啊中封装元组
            # 本次循环无返回。
    

    说明:上述情况的三种返回值

    # 1、无返回值 None
    表示本次循环中认证组件不产生任何作用,会进行到下一个循环,表示配置文件中列表可以有多个认证对象
    
    # 2、抛出异常
    raise "认证失败"
    
    # 3.函数终止,对象啊中封装元组
    两个值 self.user,self.auth
    

1.源码分析

  • 与认证类似,权限与认证流程相似,因为请求都要经过dispatch

    def dispatch(self, request, *args, **kwargs):
        self.args = args
        self.kwargs = kwargs
        request = self.initialize_request(request, *args, **kwargs)
        self.request = request
        self.headers = self.default_response_headers  # deprecate?
        try:
            self.initial(request, *args, **kwargs) #进入功能
            if request.method.lower() in self.http_method_names:
                handler = getattr(self, request.method.lower(),
                                  self.http_method_not_allowed)
            else:
                handler = self.http_method_not_allowed
            response = handler(request, *args, **kwargs)
        except Exception as exc:
            response = self.handle_exception(exc)
        self.response = self.finalize_response(request, response, *args, **kwargs)
        return self.response
    
  • initial()函数

    def initial(self, request, *args, **kwargs):
        self.format_kwarg = self.get_format_suffix(**kwargs)
        neg = self.perform_content_negotiation(request)
        request.accepted_renderer, request.accepted_media_type = neg
    
        version, scheme = self.determine_version(request, *args, **kwargs)
        request.version, request.versioning_scheme = version, scheme
    
        self.perform_authentication(request) #认证功能
        self.check_permissions(request) # 权限控制功能
        self.check_throttles(request)
    
  • check_permissions()函数

    def check_permissions(self, request):
        for permission in self.get_permissions():# 循环该对象
            if not permission.has_permission(request, self):
                # 不存在验证方法直接进入到下一个类的验证。
                # 表示定义的权限类中应该具备一个方法 has_permission()
                self.permission_denied(
                    request,
                    message=getattr(permission, 'message', None),
                    code=getattr(permission, 'code', None)
                    # 本类不存在使用反射进行获取,两个变量
                )
    
  • get_permissions()函数

    def get_permissions(self):
    	# 返回列表生成式,循环生成并存储对象。
        return [permission() for permission in self.permission_classes]
    

    image-20220406221308882

  • permission_denied()函数

    def permission_denied(self, request, message=None, code=None):
        if request.authenticators and not request.successful_authenticator:
            # 如果未认证,或认证失败则抛异常
            raise exceptions.NotAuthenticated()
        raise exceptions.PermissionDenied(detail=message, code=code)
    
  • PermissionDenied类

    class PermissionDenied(APIException):
        status_code = status.HTTP_403_FORBIDDEN
        default_detail = _('You do not have permission to perform this action.')
        default_code = 'permission_denied'
        # 可以实现定制报错消息。
    

2.简单使用(局部)

class SimplePermission(object):
    def has_permission(self,request,*args,**kwargs):
        # 返回 True 可以访问
        #if request.user.user_type != 3:
        #     return False # 返回False无权访问;
        return False

定义视图

class OrderView(APIView):
    permission_classes=[SimplePermission,]# 局部使用权限控制器
    def get(self,*args,**kwargs):
        return JsonResponse(ORDER_DICT)

image-20220407080344399

class SimplePermission(object):
    message="您没有权限访问!"# 定义返回没有权限的信息
    def has_permission(self,request,*args,**kwargs):
        # 返回 True 可以访问
        # if request.user.user_type != 3:
        #     return False # 返回False无权访问;
        return False

image-20220407081205063

3.内置权限及全局使用

# BasePermission源码,
class BasePermission(metaclass=BasePermissionMetaclass):
    """
    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):
    # 继承BasePermission
    message="您没有权限访问!!!"
    def has_permission(self, request, view):
        if request.user.user_type!=3:
            return False
        return True
REST_FRAMEWORK={
    "DEFAULT_AUTHENTICATION_CLASSES":['app01.utils.auth.MyAuthentication',],
    "UNAUTHENTICATED_USER":None, # 匿名,request.user = None
    "UNAUTHENTICATED_TOKEN":None,
    
    # 权限配置
    "DEFAULT_PERMISSION_CLASSES":['app01.utils.permission.MyPermission',],
}

注意:当配置了全局的权限控制函数后需要在登录窗口中设置权限,permission_classes = []

使用SVIP用户进行查看

image-20220407082057868

普通用户进行查看

image-20220407082526944

继续努力,终成大器!!

推荐阅读