django使用中间件限制请求ip

该文章仅仅是提供思路,代码需要根据自己需求去修改,不可全抄

限制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配置引入这个文件

路径是自己随便写的
在这里插入图片描述

评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值