频率限制

什么是频率限制

目前我们开发的都是API接口,且是开房的API接口。传给前端来处理的,也就是说,只要有人拿到这个接口,任何人都可以通过这个API接口获取数据,那么像网络爬虫的,请求速度又快,获取的数据又多,不用多久,爬虫方完全可以用我们API的接口来开发一个同样的网站,这样的话,后果就有点严重了,所以我们需要限流,限制访问的频率

开放平台的API接口调用需要限制其频率,以节约服务器资源和避免恶意的频繁调用

频率限制原理

DRF中的频率控制基本原理是基于访问次数和时间的,自然也可以通过自己定义的方法来实现。当请求进来,走到频率组件的时候,DRF内部会有一个字典来记录访问者的IP,以这个访问者的IP为key,value为一个列表,存放访问者每次访问的时间:

  {  IP1: [第三次访问时间,第二次访问时间,第一次访问时间],}

把每次访问最新时间放入列表的最前面,记录这样一个数据结构后,如果我们设置的是10秒内只能访问5次:

  1. 判断访问者的IP是否在这个请求IP的字典里
  2. 保证这个列表里都是最近10秒内的访问的时间,判断当前请求时间和列表里最早的(也就是最后的)请求时间差,如果差大于10秒,说明请求以及不是最近10秒内的,删除掉,继续判断倒数第二个,直到差值小于10秒
  3. 判断列表的长度(即访问次数),是否大于我们设置的5次,如果大于就限流,否则放行,并把时间放入列表的最前面

局部限流

和前面的认证组件,权限组件都一个套路了

url:

在项目根目录创建一个utils文件夹,在该文件夹下创建一个throttle文件,其内定义一个限流类,allow_request和wait自然也是必须要定义的方法

view:

访问:

再迅速刷新几次,立马出现限流:

相关代码:

from rest_framework.views import APIView
from rest_framework.views import Response
from utils.auth import MyAuth
from utils.permisson import MyPermission
from utils.throttle import MyThrottle
from DRF.models import User
import uuid

class DemoView(APIView):
    def get(self, request):
        return Response('简单认证')

class LoginView(APIView):
    def get(self, request):
        return Response('请登录,如果没有账号请创建')

    def post(self, request):
        user = request.data.get('user')
        pwd = request.data.get('pwd')
        token = uuid.uuid4()
        User.objects.create(user=user, pwd=pwd, token=token)
        return Response('创建用户成功')

class TestView(APIView):
    authentication_classes = [MyAuth, ]
    permission_classes = [MyPermission, ]
    throttle_classes = [MyThrottle,]

    def get(self, request):
        return Response('权限等级测试,VIP用户您好,欢迎访问XX。。。')

View

from rest_framework.throttling import SimpleRateThrottle
import time

VISIT_RECORD = {}

class MyThrottle(BaseThrottle):
    def __init__(self):
        self.history = None

    def allow_request(self, request, view):
        # 以IP作为限流
        # 1.获取请求IP
        ip = request.META.get('REMOTE_ADDR')
        now = time.time()
        # 2.判断是否在访问列表
        if ip not in VISIT_RECORD:
            VISIT_RECORD[ip] = [now, ]
            return True
        history = VISIT_RECORD[ip]
        history.insert(0, now)
        # 3.确保访问列表最多保存不能超过一分钟的
        while history and history[0] - history[-1] > 60:
            history.pop()
        self.history = history
        # 4.如果列表超过允许长度
        if len(history) > 3:
            return False
        else:
            return True

    def wait(self):
        # 返回需要等待的时间
        time = 60 - (self.history[0] - self.history[-1])
        return time

throttle

from django.urls import path, re_path
from DRF.views import DemoView, LoginView, TestView

urlpatterns = [
    path(r'', DemoView.as_view()),
    re_path(r'^login/', LoginView.as_view()),
    re_path(r'^test/', TestView.as_view()),
]

url

全局限流

也不用多说,自然是在配置文件里配置:

这样配置重启后就不仅是test视图里有限流了,其他的视图类也会有的

DRF自带的限流类

在framework.throttling里,有很多的已经定义好的类

其他都不变,改下自定义的限流类,这次继承SimpleRateThrottle类:

配置文件里做如下配置:

重启访问:

多次刷新后得,跟我们之前自定义的类一致

相关代码:

from rest_framework.views import APIView
from rest_framework.views import Response
from utils.auth import MyAuth
from utils.permisson import MyPermission
from utils.throttle import MyThrottle
from DRF.models import User
import uuid

class DemoView(APIView):
    def get(self, request):
        return Response('简单认证')

class LoginView(APIView):
    def get(self, request):
        return Response('请登录,如果没有账号请创建')

    def post(self, request):
        user = request.data.get('user')
        pwd = request.data.get('pwd')
        token = uuid.uuid4()
        User.objects.create(user=user, pwd=pwd, token=token)
        return Response('创建用户成功')

class TestView(APIView):
    authentication_classes = [MyAuth, ]
    permission_classes = [MyPermission, ]
    throttle_classes = [MyThrottle,]

    def get(self, request):
        return Response('权限等级测试,VIP用户您好,欢迎访问XX。。。')

View

from rest_framework.throttling import SimpleRateThrottle
import time

class MyThrottle(SimpleRateThrottle):
    scope = 'thro' # 限流的配置文件key

    def get_cache_key(self, request, view):
        # 如果以IP地址做限流返回IP地址
        return self.get_ident(request)

throttle

REST_FRAMEWORK = {
    # "DEFAULT_VERSIONING_CLASS": "utils.version.MyVersion",
    "DEFAULT_VERSIONING_CLASS": "rest_framework.versioning.QueryParameterVersioning",
    "DEFAULT_VERSION": "v1",
    "ALLOWED_VERSIONS": "v1, v2",
    "VERSION_PARAM": "ver",
    # "DEFAULT_AUTHENTICATION_CLASSES": ["utils.auth.MyAuth", ],
    "DEFAULT_THROTTLE_RATES": {
        "WD": "3/m"
    }
}

settings

总结:

  • 自定义限流频率类,必须继承DRF定义好的类,需要用什么就继承什么,且根据继承的类不同,必须要定义该基类里明确规定需要的方法或者属性
  • 限流频率组件必须在认证组件和权限组件验证通过之后才作验证(这是按开发逻辑来的)
  • 全局和局部都还是那一套,不用再多说什么,跟前面的认证组件,权限组件都一个套路

前后端分离djangorestframework——限流频率组件的更多相关文章

  1. 前后端分离djangorestframework——分页组件

    Pagination 为什么要分页也不用多说了,大家都懂,DRF也自带了分页组件 这次用  前后端分离djangorestframework——序列化与反序列化数据  文章里用到的数据,数据库用的my ...

  2. 前后端分离djangorestframework——路由组件

    在文章前后端分离djangorestframework——视图组件 中,见识了DRF的视图组件强大,其实里面那个url也是可以自动生成的,就是这么屌 DefaultRouter urls文件作如下调整 ...

  3. 前后端分离djangorestframework——视图组件

    CBV与FBV CBV之前说过就是在view.py里写视图类,在序列化时用过,FBV就是常用的视图函数,两者的功能都可以实现功能,但是在restful规范方面的话,CBV更方便,FBV还要用reque ...

  4. 前后端分离djangorestframework—— 在线视频平台接入第三方加密防盗录视频

    加密视频 在以后的开发项目中,很可能有做在线视频的,而在线视频就有个问题,因为在线播放,就很有可能视频数据被抓包,如果这个在线视频平台有付费视频的话,这样就会有人做点倒卖视频的生意了,针对这个问题,目 ...

  5. 前后端分离djangorestframework—— 接入第三方的验证码平台

    关于验证码部分,在我这篇文章里说的挺详细的了:Python高级应用(3)—— 为你的项目添加验证码 这里还是再给一个前后端分离的实例,因为极验官网给的是用session作为验证的,而我们做前后端分离的 ...

  6. 前后端分离djangorestframework——认证组件

    authentication 认证是干嘛的已经不需要多说.而前后端未分离的认证基本是用cookie或者session,前后端分离的一般用token 全局认证 先创建一个django项目,项目名为drf ...

  7. 前后端分离djangorestframework——序列化与反序列化数据

    我们写好后端的代码,要把数据交给前端的展示的,这个数据以什么类型给前端呢?学到这里,我们已经知道这个数据最好是json字符串才行,因为网络间的传输,只认字符串或者二进制,字符串就是我们的数据,二进制就 ...

  8. 前后端分离djangorestframework——restful规范

    restful现在非常流行,所以很有必要提一下 web服务交互 在浏览器中能看到的每个网站,都是一个web服务.那么我们在提供每个web服务的时候,都需要前后端交互,前后端交互就一定有一些实现方案,我 ...

  9. 前后端分离djangorestframework——ContentType组件表

    ContentType ContentType其实django自带的,但是平时的话很少会用到,所以还是放在Djangorestframework这个部分 作用: 在实际的开发中,由于数据库量级大,所以 ...

随机推荐

  1. python练习四—简单的聊天软件

    python最强大的是什么?库支持!!有了强大的库支持,一个简单的聊天软件实现就更简单了,本项目思路如下 # 项目思路 1. 服务器的工作 * 初始化服务器 * 新建一个聊天房间 * 维护一个已链接用 ...

  2. LINUX服务器搭建和常用配置介绍

    服务器搭建 : 搭建私有CA服务器 : http://www.cnblogs.com/zhaojiedi1992/p/zhaojiedi_linux_011_ca.html搭建samba服务器 : h ...

  3. Java网络编程的Java流介绍

    前言 网络程序所做的很大一部分工作都是简单的输入输出:将数据字节从一个系统移动到另一个系统.Java的I/O建立于流(stream)之上.输入流读取数据,输出流写入数据.过滤器流(filter)流可以 ...

  4. 2016 ACM/ICPC亚洲区青岛站现场赛(部分题解)

    摘要 本文主要列举并求解了2016 ACM/ICPC亚洲区青岛站现场赛的部分真题,着重介绍了各个题目的解题思路,结合详细的AC代码,意在熟悉青岛赛区的出题策略,以备战2018青岛站现场赛. HDU 5 ...

  5. 【转】JSP中的JSTL与EL表达式用法及区别

    对于JSTL和EL之间的关系,这个问题对于初学JSP的朋友来说,估计是个问题,下面来详细介绍一下JSTL和EL表达式他们之间的关系,以及JSTL和EL一些相关概念! EL相关概念JSTL一般要配合EL ...

  6. [转]Database Transactions in Laravel

    本文转自:https://fideloper.com/laravel-database-transactions Laravel's documentation on Database Transac ...

  7. camera测试之MTF

    1.MTF介绍 MTF(Modulation Transfer Function)模量传递函数.MTF是camera成像对比度和分辨率的综合表现.从另一个角度来看,camera成像过程可以简单看成下图 ...

  8. 用Vue.js搭建一个小说阅读网站

    目录 1.简介 2.如何使用vue.js 3.部署api服务器 4.vue.js路由配置 5.实现页面加载数据 6.测试vue项目 7.在正式环境部署 8.Vue前端代码下载 1.简介 这是一个使用v ...

  9. C# 动态代码生成控件后其他事件不能获取该控件的值

    1.新建web项目,添加两个Button控件,结果如图. 2.Button按钮控件点击事件代码如下 protectedvoid Button1_Click(object sender, EventAr ...

  10. Hibernate-在Eclipse(Oxygen)中安装Hibernatetools插件

    Eclipse(Luna)中是没有Hibernate插件的,该插件是需要自己进行添加. 在网上找了一下关于如何在Eclipse中安装Hibernatetools插件的方法,很多都是先找到Hiberna ...