该文章仅仅是提供思路,代码需要根据自己需求去修改,不可全抄
限制ip访问次数, 同一ip一分钟内访问次数不超过60次
Django2.0.2 + py37
1. 在某个地方建一个LimitIp.py文件(位置以及文件名自定义,只需要在settings.py中引入就好)
# -*- coding:utf-8 -*-
# @Time : 2021/5/15 15:31
# @Author : xx
# @File : limit_ip.py
# @Software: PyCharm
# @desc: 限制ip请求次数
import time
from django.http import JsonResponse
from django.utils.deprecation import MiddlewareMixin
from utils.common import type_reversal
from utils.redis_cache import redis_client # 就是一个redis连接池,等同于mysql连接后的conn
from PythonDjangoApi.settings import limit_time, clean_time #
#limit_time = 120 # 禁用时间单位秒
#clean_time = 24 * 60 * 60 # 该IP多长时间不访问,redis自动清理时间为1day = 24 * 60 * 60s
class LimitIp(MiddlewareMixin):
"""限制ip"""
conn = redis_client.get_connection("limit_ip")
def process_request(self, request):
ip = str(request.META.get("REMOTE_ADDR"))
time_now = time.time()
data = type_reversal(self.conn.get(ip), True)
if data:
if data["disable"] == 1 and data["allow_time"] - time_now > 0:
return JsonResponse({"code": 403, "msg": f"访问过于频繁,请于{limit_time / 60}分钟后再试"})
record = data["record"]
while 1:
if record and time_now - record[0] > 60:
record.pop(0)
else:
break
if len(record) >= 60:
record.append(time_now)
data["disable"] = 1
data["allow_time"] = limit_time + time_now
record.append(time_now)
self.conn.setex(ip, clean_time, type_reversal(data))
return JsonResponse({"code": 403, "msg": f"访问过于频繁,请于{limit_time / 60}分钟后再试"})
else:
"""一分钟次数没超过60"""
data["disable"] = 0
data["allow_time"] = 0
record.append(time_now)
self.conn.setex(ip, clean_time, type_reversal(data))
return
data = {"record": [], "disable": 0, "allow_time": 0}
data["record"].append(time_now)
self.conn.setex(ip, clean_time, type_reversal(data))
return
if __name__ == '__main__':
import json
conn = redis_client.get_connection("limit_ip")
data = conn.get("127.0.0.1")
# conn.set("127.0.0.1", json.dumps({"record": [], "disable": 0, "allow_time": 0}))
print(data)
上方文件引入的一些方法
def type_reversal(data, reverse=False):
"""
将list,dict等转化为str
:param reverse = True 则将str转化为对应类型
"""
if data:
if reverse:
return json.loads(data)
return json.dumps(data)
return None
2. 然后再settings.py配置引入这个文件
路径是自己随便写的