zoukankan      html  css  js  c++  java
  • rest-framework之频率控制 ——自定义频率类,自定义频率规则,内置频率类及局部使用

    1.不存数据库的token认证

    import hashlib
    from day98 import settings
    
    
    def check_token(token):
        ret = True
        user_info = None
        try:
            ll = token.split('|')
            # da89744b701b5d8bc5b9a76b4ddb3dd4 , {"name": "cao", "id": 1},已经切分成了一个列表
            md5 = hashlib.md5()
            # 需要给这个{"name": "cao", "id": 1}加密,它就是列表里的第一个值
            md5.update(ll[1].encode('utf-8'))
            # 在setting里面全局配置一下,给token加盐
            md5.update(settings.password.encode('utf-8'))
            # hex=da89744b701b5d8bc5b9a76b4ddb3dd4
            hex = md5.hexdigest()
            if not hex == ll[0]:
                ret = False
            else:
                user_info = ll[1]
        except Exception as e:
            ret = False
        return ret, user_info
    
    
    class LoginAuth(BaseAuthentication):
        # 函数名一定要叫authenticate,需要接收2个参数,第二个参数是request对象
        def authenticate(self, request):
            # 从request对象中取出token(也可以从其他地方取)
            token = request.query_params.get('token')
            # ret是布尔类型,表示验证通过或者失败,user_info是user的字典
            ret, user_info = check_token(token)
            if ret:
                # 能查到,说明认证通过,反回空
                # ret.user就是当前登录用户对象
                return user_info, None
            # 如果查不到,就抛出异常
            raise exceptions.APIException('认证失败')
    MyAuth.py-认证组件
    class Books(APIView):
        # 列表中类名不能加括号
        authentication_classes = [LoginAuth, ]
    
        def get(self, request, *args, **kwargs):
            # 只要通过认证,就能取到当前登录用户对象的密码,id等信息
            # print(request.query_params)
            print(request.user)
            # print(request.user.pwd)
            response = {'status': 100, 'msg': '查询成功'}
            res = models.Book.objects.all()
            book_ser = MySerializer.BookSerializer(res, many=True)
            # 这个数据是需要返回给前台的
            response['data'] = book_ser.data
            # print(book_ser.data)
            return JsonResponse(response, safe=False)
    
    
    # 登录接口,不存数据库的token认证
    import json
    
    from day98 import settings
    
    
    def create_token(user_pk):
        md5 = hashlib.md5()
        md5.update(user_pk.encode('utf-8'))
        # 在setting里面全局配置一下,给token加盐
        md5.update(settings.password.encode('utf-8'))
        hex = md5.hexdigest()
        token = '|'.join([hex, user_pk])
        # token=hex+'|'+user_info
        print(token)
        return token
    
    
    class Login(APIView):
        authentication_classes = []
    
        # 登录就是使用post,get是返回一个页面
        def post(self, request, *args, **kwargs):
            response = {'status': 100, 'msg': '登录成功'}
            name = request.data.get('name')
            pwd = request.data.get('pwd')
            try:
                user = models.UserInfo.objects.get(name=name, pwd=pwd)
                user_info_json = json.dumps({'name': user.name, 'id': user.pk})
                # 生成vfvevberber|{'name': user.name, 'id': user.pk}的token
                token = create_token(str(user.pk))
                # 登陆成功之后把登录返回给他,以后就带着token过来
                response['token'] = token
            except ObjectDoesNotExist as e:
                response['status'] = 101
                response['msg'] = '用户名或密码错误'
    
            except Exception as e:
                # 万能异常,里面只要出错,程序就会走到这里
                response['status'] = 102
                # response['msg'] = '未知错误'
                # 把整个错误信息转换成str类型,赋值给e,一般在测试时使用这个
                response['msg'] = str(e)
                # 如果不写safe=False,只能序列化字典形式,如果字典里面又套了列表,或者直接是一个列表,就必须写safe=False
            return JsonResponse(response, safe=False)
    View.py-登录接口

    频率简介:

    节流,访问控制。为了控制用户对某个url请求的频率,比如,一分钟以内,只能访问三次 
    内置的访问频率控制类:SimpleRateThrottle
    -写一个类,继承SimpleRateThrottle

    2.自定义频率类,自定义频率规则

    from rest_framework.throttling import BaseThrottle
    import time
    

    MyAuth.py-频率控制
    # 频率控制
    '''
    自定义的逻辑:
    {'ip1':[时间1 ,时间2],
    'ip2':[时间1, ],
    (1)取出访问者ip
    (2)判断当前ip不在访问字典里,添加进去,并且直接返回True,表示第一次访问,在字典里,继续往下走
    (3)循环判断当前ip的列表,有值,并且当前时间减去列表的最后一个时间大于60s,把这种数据pop掉,这样列表中只有60s以内的访问时间
    (4)判断,当列表小于3,说明一分钟以内访问不足三次,把当前时间插入到列表第一个位置,返回True,顺利通过
    (5)当大于等于3,说明一分钟内访问超过三次,返回False验证失败
    '''
    class MyThrottle():
    visitor_dic = {}
    def __init__(self):
    self.history=None

    def allow_request(self, request, view):
    # META:请求所有的东西的字典
    # 拿出ip地址
    ip = request.META.get('REMOTE_ADDR')
    # 判断id在不在字典里面,不在字典里面,说明是第一次访问
    ctime = time.time()
    if ip not in self.visitor_dic:
    self.visitor_dic[ip] = [ctime, ]
    return True
    # 根据当前访问者的ip,取出访问者的时间列表
    history = self.visitor_dic[ip]
    # 记录一下当前访问者的ip
    self.history=history
    # 如果时间大于这个值,说明是一分钟之后访问的,那么就删除一分钟之后访问的
    while history and ctime - history[-1] > 60:
    history.pop()
    # 一分钟访问小于三次
    if len(history) < 3:
    # 就把当前时间放在第0个位置上
    history.insert(0, ctime)
    return True
    else:
    return False

    def wait(self):
    # 剩余时间 # 要取列表里的最后一个值
      ctime=time.time() # 当前时间减去最后一次访问的时间
      return 60-(ctime-self.history[-1])

    view视图层
    from django.shortcuts import render, HttpResponse
    from rest_framework import exceptions

    from rest_framework.views import APIView
    from app01.myAuth import MyThrottle
    from rest_framework.parsers import JSONParser, FormParser



    class Test(APIView):
    throttle_classes = [MyThrottle, ]

    def get(self, request):
    return HttpResponse('ok')

    3.内置频率类及局部使用

    -内置的访问频率控制类(根据ip限制):SimpleRateThrottle
    -写一个类,继承SimpleRateThrottle
    
    MyAuth.py-频率控制
    from rest_framework.throttling import BaseThrottle, SimpleRateThrottle
    class MyThrottle(SimpleRateThrottle):
        scope = 'aaa'
    
        def get_cache_key(self, request, view):
            # 返回ip地址
            # ip=request.META.get('REMOTE_ADDR')
            # return ip
            return self.get_ident(request)

    settings.py
    STATIC_URL = '/static/'
    REST_FRAMEWORK = {
    # 'DEFAULT_THROTTLE_CLASSES': ['app01.myAuth.MyThrottle', ],
    'DEFAULT_THROTTLE_RATES': {
    # 每分钟访问10次
    'aaa': '5/m'
    }
    }


    使用:
    局部使用: -在视图类中写 throttle_classes = [MyThrottle,]
    全局使用: 在settings中配置:
    REST_FRAMEWORK = {
    'DEFAULT_AUTHENTICATION_CLASSES': ['app01.MyAuth.LoginAuth', ],
    # 'DEFAULT_PERMISSION_CLASSES': ['app01.MyAuth.UserPermission', ]
    }          
          -局部禁用:
               -在视图类中写
               throttle_classes = []

    4.错误信息改成中文显示

                def throttled(self, request, wait):
                    class MyThrottled(exceptions.Throttled):
                        default_detail = '傻逼'
                        extra_detail_singular = '还剩 {wait} 秒.'
                        extra_detail_plural = '还剩 {wait} 秒'
    
                    raise MyThrottled(wait)
  • 相关阅读:
    10 道选择题,测试你是不是死忠谷粉
    JBoss Seam 3.0.0.Beta2 发布
    送给十二星座的名言警句
    Chinasb & B3log!
    GAE 博客——B3log Solo 0.2.5 正式版发布了!
    明天发布 B3log Solo 0.2.5
    JBoss Seam 3.0.0.Beta2 发布
    10 道选择题,测试你是不是死忠谷粉
    Python数据分析工具包:Pandas
    Programming Computer Vision with Python: Tools and algorithms for analyzing images
  • 原文地址:https://www.cnblogs.com/cao123/p/10120305.html
Copyright © 2011-2022 走看看