zoukankan      html  css  js  c++  java
  • DRF认证、权限、频率组件。

    一:基本知识

        1:该三个组件阅读源码的方式和版本源码阅读步骤类似。详细阅读版本源码https://www.cnblogs.com/yingjp/p/10606698.html

        2:进入initial可以看到以下方法

            #认证执行的方法
            self.perform_authentication(request)
            #权限执行的方法
            self.check_permissions(request)
            #频率执行的方法
            self.check_throttles(request)
    

     3:进一步对上述的方法进行阅读我们能得出以下几点。

         a:在settings中应该怎样配置

         b:自定义组件需要实现什么方法

         c:方法的返回值

         d:对应的属性取值的方法 

       4:对认证,权限,频率这三个逐渐学习步骤

           a:用rest_framework给我们提供的模块进行定制

           b:自己定义组件

    二:认证组件

          1:阅读源码结论

             a:认证类需要继承BaseAuthentication类

             b:需要实现authenticate(self, request)方法

             c:返回一个长度为2的元祖。

             d:settings可以通过'DEFAULT_AUTHENTICATION_CLASSES'配置全局的验证。

          2:自定义认证类(配置全局认证)

               a;先写一个认证类

    from  rest_framework.authentication import BaseAuthentication
    from testDemo.models import UserInfo
    from rest_framework.exceptions import AuthenticationFailed
    
    '''
    这里是写的token是存在url中
      1:需要继承BaseAuthentication
      2:需要重写authenticate()方法
      3:返回一个元祖
    '''
    
    class  MyAuth(BaseAuthentication):
        #自定义token在url中
        def authenticate(self, request):
            token = request.query_params.get('token','')
            user=UserInfo.objects.filter(token=token).first()
            if not user:
                raise AuthenticationFailed('token 信息不合理')
    
            return (user,token)
    

        b:settings注册

               --所有的视图函数都会进行认证,其实还不是很必要。局部认证在下面写

      

    REST_FRAMEWORK={
        #认证注册
        'DEFAULT_AUTHENTICATION_CLASSES':['utils.auth.MyAuth',],
    }
    

      3:使用rest_framework提供的认证组件进行认证。

              说明:认证组件一般都是自己写的,这里介绍自定义组件只是了解,学习视图函数的局部认证。          

              a:通过BaseAuthentication这个认证的基类,点进去就能看见所有人认证类了。使用方式和自定义的认证类一样

            b:局部视图的认证,在需要认证的视图处添加authentication_classes=[authclass1,authclass2]

    from utils.auth import MyAuth
    # Create your views here.
    from rest_framework.views import APIView,Response
    import uuid
    from testDemo.models import UserInfo
    # Create your models here.
    class authDemo(APIView):
        authentication_classes = [MyAuth, ]
        def get(self, request):
            print(request.user)
            print(request.auth)
            return Response('测试代码')  

    三:权限组件

        1:阅读代码结论

           1:settings全局配置 key'DEFAULT_PERMISSION_CLASSES'

           2:视图函数局部配置参数 permission_classes

           3:权限类需要继承的类 from rest_framework.permissions import BasePermission

           4:需要重写的方法 has_permission(self, request, view):

        2:自定义权限类

    from rest_framework.permissions import BasePermission
    
    class   MyPermissions(BasePermission):
        def   has_permission(self, request, view):
            #登陆成功后登陆信息,存在request.user中
            user_obj =request.user
            #type ==3 普通用户  没有该权限
            if user_obj.type ==3:
                return False
            return True
    

     3:权限配置:       

           参考第一条。略 

    四:频率组件

      说明:为了防止恶意访问,需要对同一个访问者进行访问频率控制,来减少服务器压力。

      1:频率组件实现原理

        DRF频率控制是通过单位时间内访问的次数来实现。在DRF的内部有一个字典,当一个iP访问的时候,如果IP1是已经访问的ip则在记录字典中添加这次的访问时间。

        {'ip1':[时间1,时间2,最新时间]}。如果IP2是第一次访问,则该字典进行添加操作{'ip2':[最新访问时间]}

     2:源码阅读结论(略)

          --小结会总结源码快捷阅读技巧。

     3:自定义频率控制类

    from rest_framework.throttling import BaseThrottle
    import time
    VISIT_RECORD = {}
    class   MyThrotting(BaseThrottle):
        def  __init__(self):
            self.history=[]
        #方法实现
        def allow_request(self, request, view):
            """
             以IP限流  一分钟同一个IP只能访问五次
            """
            #1:获取发访问一个ip
            ip = request.META.get("REMOTE_ADDR")
            '''
             2:判断当前ip是否存在,如果存在,添加最新的时间,如果不存在添加新的ip
            '''
            now_time=time.time()
            if  ip  in VISIT_RECORD:
                VISIT_RECORD[ip].insert(0,now_time)
            else:
                VISIT_RECORD[ip]=[now_time]
            history=VISIT_RECORD[ip]
            '''
            3:最后访问的和最新访问的时间相差一秒,删除最早访问的记录。保证字典内的记录均在一分钟以内。
            '''
            while history  and history[0]-history[-1]>60:
                history.pop()
            self.history=history
            """
            4:判断一分钟内,该ip访问次数是不是5次  
            """
            if len(history) > 5:
                return False
            else:
                return True
    
        def wait(self):
            """
            需要等待多长时间,才能再次访问
            """
            time = 60 - (self.history[0] - self.history[-1])
            return time
    

     4:局部配置和全局配置

           --略

     4:框架提供的频率认证组件的使用 

        1:导入包   

          --from rest_framework.throttling import SimpleRateThrottle

        2:settings配置

              --其他一些符号代表的时间频率

              --('s', 'sec', 'm', 'min', 'h', 'hour', 'd', 'day')

    REST_FRAMEWORK = {
        
        "DEFAULT_THROTTLE_RATES":{
            'WD':'5/m',         #速率配置每分钟不能超过5次访问,WD是scope定义的值,
    
        }
    }
    

        3:类的编写

    from rest_framework.throttling import BaseThrottle,SimpleRateThrottle
    class MyVisitThrottle(SimpleRateThrottle):
        #与settings配置的一样
        scope = "WD"
    
        def get_cache_key(self, request, view):
            return self.get_ident(request)
    

        4:局部使用   

    class authDemo(APIView):
        throttle_classes=[MyVisitThrottle]
        def get(self, request):
            return Response('测试代码')
    

      

    五:小结  

         1:源码快速阅读总结

           a:观察框架实现的组件,可以发现导入规律

              -- rest_framework.组件英文拼写 import Base英文拼写

    from rest_framework.throttling import BaseThrottle
    from rest_framework.authentication import BaseAuthentication
    from rest_framework.permissions import BasePermission
    

            b:点进对应的方法,下面均有不同的实现,但是可以看到需要重写什么方法。这样就能自定义组件了

       2:组件阅读源码快速配置

           a:setings一定配置 REST_FRAMEWORK={}

            一定要写

    REST_FRAMEWORK = {}
        

           a:进入视图继承类APIView

              --中文注释我自己写的,是不是正好可以得出中文注释结论

              --全局配置key是 = 后面的值,

              --局部配置在 = 前面的参数  

     renderer_classes = api_settings.DEFAULT_RENDERER_CLASSES
        parser_classes = api_settings.DEFAULT_PARSER_CLASSES
        '''
          权限认证
        '''
        authentication_classes = api_settings.DEFAULT_AUTHENTICATION_CLASSES
        '''
        频率认证
        '''
        throttle_classes = api_settings.DEFAULT_THROTTLE_CLASSES
        '''
        权限认证
        '''
        permission_classes = api_settings.DEFAULT_PERMISSION_CLASSES
        content_negotiation_class = api_settings.DEFAULT_CONTENT_NEGOTIATION_CLASS
        metadata_class = api_settings.DEFAULT_METADATA_CLASS
        
        '''
        版本认证
        '''
        versioning_class = api_settings.DEFAULT_VERSIONING_CLASS
    

      

             

             

              

        

  • 相关阅读:
    c++中 . 和 -> 的区别是什么?
    codeblocks中一个简单的程序的创建。
    将牛客中的代码在codeblocks中进行实现
    (全代码)输入一颗二叉树的跟节点和一个整数,打印出二叉树中结点值的和为输入整数的所有路径。路径定义为从树的根结点开始往下一直到叶结点所经过的结点形成一条路径。(注意: 在返回值的list中,数组长度大的数组靠前)
    解决You are using pip version 10.0.1, however version 18.1 is available. You should consider upgrading via the 'python -m pip install --upgrade pip' command.
    mysql 表复制(表备份)
    Scrapy 抓取股票行情
    去哪儿网数据爬取
    用API爬取天气预报数据
    爬虫防封IP
  • 原文地址:https://www.cnblogs.com/yingjp/p/10608968.html
Copyright © 2011-2022 走看看