zoukankan      html  css  js  c++  java
  • day11 —— DRF 进阶6 自定制频率、接口文档、JWT

     

    1.自定制频率

     
    # 自定制频率类,需要写两个方法
    	-# 判断是否限次:没有限次可以请求True,限次了不可以请求False
        	defallow_request(self, request, view):
        -# 限次后调用,显示还需等待多长时间才能再访问,返回等待的时间seconds
        	defwait(self):
                
    # 代码
    import time
    classIPThrottle():
        #定义成类属性,所有对象用的都是这个
        VISIT_DIC = {}
        def__init__(self):
            self.history_list=[]
        defallow_request(self, request, view):
            '''
            #(1)取出访问者ip
            #(2)判断当前ip不在访问字典里,添加进去,并且直接返回True,表示第一次访问,在字典里,继续往下走
            #(3)循环判断当前ip的列表,有值,并且当前时间减去列表的最后一个时间大于60s,把这种数据pop掉,这样列表中只有60s以内的访问时间,
            #(4)判断,当列表小于3,说明一分钟以内访问不足三次,把当前时间插入到列表第一个位置,返回True,顺利通过
            #(5)当大于等于3,说明一分钟内访问超过三次,返回False验证失败
            '''
    
            ip=request.META.get('REMOTE_ADDR')
            ctime=time.time()
            if ip not in self.VISIT_DIC:
                self.VISIT_DIC[ip]=[ctime,]
                return True
            self.history_list=self.VISIT_DIC[ip]   #当前访问者时间列表拿出来
            while True:
                if ctime-self.history_list[-1]>60:
                    self.history_list.pop() # 把最后一个移除
                else:
                    break
            if len(self.history_list)<3:
                self.history_list.insert(0,ctime)
                return True
            else:
                return False
    
        defwait(self):
            # 当前时间,减去列表中最后一个时间
            ctime=time.time()
    
            return 60-(ctime-self.history_list[-1])
    
    #全局使用,局部使用
    
    
     
    # SimpleRateThrottle源码分析
        defget_rate(self):
            """
            Determine the string representation of the allowed request rate.
            """
            if not getattr(self, 'scope', None):
                msg = ("You must set either `.scope` or `.rate` for '%s' throttle" %
                       self.__class__.__name__)
                raise ImproperlyConfigured(msg)
    
            try:
                return self.THROTTLE_RATES[self.scope]  # scope:'user' => '3/min'
            except KeyError:
                msg = "No default throttle rate set for '%s' scope" % self.scope
                raise ImproperlyConfigured(msg)
        defparse_rate(self, rate):
            """
            Given the request rate string, return a two tuple of:
            <allowed number of requests>, <period of time in seconds>
            """
            if rate is None:
                return (None, None)
            #3  mmmmm
            num, period = rate.split('/')  # rate:'3/min'
            num_requests = int(num)
            duration = {'s': 1, 'm': 60, 'h': 3600, 'd': 86400}[period[0]]
            return (num_requests, duration)
        defallow_request(self, request, view):
            if self.rate is None:
                return True
            #当前登录用户的ip地址
            self.key = self.get_cache_key(request, view)  # key:'throttle_user_1'
            if self.key is None:
                return True
    
            # 初次访问缓存为空,self.history为[],是存放时间的列表
            self.history = self.cache.get(self.key, [])
            # 获取一下当前时间,存放到 self.now
            self.now = self.timer()
    
            # Drop any requests from the history which have now passed the
            # throttle duration
    
            # 当前访问与第一次访问时间间隔如果大于60s,第一次记录清除,不再算作一次计数
            # 10 20 30 40
            # self.history:[10:23,10:55]
            # now:10:56
            while self.history and  self.now - self.history[-1] >= self.duration:
                self.history.pop()
    
            # history的长度与限制次数3进行比较
            # history 长度第一次访问0,第二次访问1,第三次访问2,第四次访问3失败
            if len(self.history) >= self.num_requests:
                # 直接返回False,代表频率限制了
                return self.throttle_failure()
    
            # history的长度未达到限制次数3,代表可以访问
            # 将当前时间插入到history列表的开头,将history列表作为数据存到缓存中,key是throttle_user_1,过期时间60s
            return self.throttle_success()
    
    

    2.自动生成接口文档

     
    # 1 安装:pip install coreapi
    
    # 2 在路由中配置
    	from rest_framework.documentation import include_docs_urls
        urlpatterns = [
            ...
            path('docs/', include_docs_urls(title='站点页面标题'))
        ]
    #3 视图类:自动接口文档能生成的是继承自APIView及其子类的视图。
    	-1 ) 单一方法的视图,可直接使用类视图的文档字符串,如
            classBookListView(generics.ListAPIView):
                """
                返回所有图书信息.
                """
        -2)包含多个方法的视图,在类视图的文档字符串中,分开方法定义,如
            classBookListCreateView(generics.ListCreateAPIView):
                """
                get:
                返回所有图书信息.
                post:
                新建图书.
                """
        -3)对于视图集ViewSet,仍在类视图的文档字符串中封开定义,但是应使用action名称区分,如
            classBookInfoViewSet(mixins.ListModelMixin, mixins.RetrieveModelMixin, GenericViewSet):
            """
            list:
            返回图书列表数据
            retrieve:
            返回图书详情数据
            latest:
            返回最新的图书数据
            read:
            修改图书的阅读量
            """
    

    3.JWT

     
    jwt=Json Web token
    #原理
    """
    1)jwt分三段式:头.体.签名 (head.payload.sgin)
    2)头和体是可逆加密,让服务器可以反解出user对象;签名是不可逆加密,保证整个token的安全性的
    3)头体签名三部分,都是采用json格式的字符串,进行加密,可逆加密一般采用base64算法,不可逆加密一般采用hash(md5)算法
    4)头中的内容是基本信息:公司信息、项目组信息、token采用的加密方式信息
    {
    	"company": "公司信息",
    	...
    }
    5)体中的内容是关键信息:用户主键、用户名、签发时客户端信息(设备号、地址)、过期时间
    {
    	"user_id": 1,
    	...
    }
    6)签名中的内容时安全信息:头的加密结果 + 体的加密结果 + 服务器不对外公开的安全码 进行md5加密
    {
    	"head": "头的加密字符串",
    	"payload": "体的加密字符串",
    	"secret_key": "安全码"
    }
    """
    
    校验
    """
    1)将token按 . 拆分为三段字符串,第一段 头加密字符串 一般不需要做任何处理
    2)第二段 体加密字符串,要反解出用户主键,通过主键从User表中就能得到登录用户,过期时间和设备信息都是安全信息,确保token没过期,且时同一设备来的
    3)再用 第一段 + 第二段 + 服务器安全码 不可逆md5加密,与第三段 签名字符串 进行碰撞校验,通过后才能代表第二段校验得到的user对象就是合法的登录用户
    """
    
    drf项目的jwt认证开发流程(重点)
    """
    1)用账号密码访问登录接口,登录接口逻辑中调用 签发token 算法,得到token,返回给客户端,客户端自己存到cookies中
    
    2)校验token的算法应该写在认证类中(在认证类中调用),全局配置给认证组件,所有视图类请求,都会进行认证校验,所以请求带了token,就会反解出user对象,在视图类中用request.user就能访问登录的用户
    
    注:登录接口需要做 认证 + 权限 两个局部禁用
    """
    
    # 第三方写好的  django-rest-framework-jwt
    # 安装pip install djangorestframework-jwt
    
    # 新建一个项目,继承AbstractUser表()
    
    # 创建超级用户
    
    # 简单使用
     #urls.py
        from rest_framework_jwt.views import ObtainJSONWebToken,VerifyJSONWebToken,RefreshJSONWebToken,obtain_jwt_token
        path('login/', obtain_jwt_token),
    
        
     
    
    

    4.自定制auth认证类

     
    from rest_framework_jwt.authentication import BaseAuthentication,BaseJSONWebTokenAuthentication
    from rest_framework.exceptions import AuthenticationFailed
    from rest_framework_jwt.authentication import jwt_decode_handler
    from rest_framework_jwt.authentication import get_authorization_header,jwt_get_username_from_payload
    from rest_framework import exceptions
    classMyToken(BaseJSONWebTokenAuthentication):
        defauthenticate(self, request):
            jwt_value=str(request.META.get('HTTP_AUTHORIZATION'))
            # 认证
            try:
                payload = jwt_decode_handler(jwt_value)
    
            except Exception:
                raise exceptions.AuthenticationFailed("认证失败")
            user=self.authenticate_credentials(payload)
            return user,None
        
    #局部使用,全局使用
    
     
     
  • 相关阅读:
    希望走过的路成为未来的基石
    第三次个人作业--用例图设计
    第二次结对作业
    第一次结对作业
    第二次个人编程作业
    第一次个人编程作业(更新至2020.02.07)
    Springboot vue 前后分离 跨域 Activiti6 工作流 集成代码生成器 shiro权限
    springcloud 项目源码 微服务 分布式 Activiti6 工作流 vue.js html 跨域 前后分离
    spring cloud springboot 框架源码 activiti工作流 前后分离 集成代码生成器
    java代码生成器 快速开发平台 二次开发 外包项目利器 springmvc SSM后台框架源码
  • 原文地址:https://www.cnblogs.com/yding/p/13320717.html
Copyright © 2011-2022 走看看