由于Http请求是无状态的,服务端能直知道是那个客户端的访问,所以,我们可以利用session技术,记住每个用户访问的状态数据。
- 在用户发起请求后,记录用户IP, 同时进行每次访问时间的统计,实现客户端的访问频率限制,IP禁止。
import time
from django.http import HttpResponse
# Create your views here.
VISIT_LIMIT = 20
TIME_INTERVAL = 10
RETRY_TIME = 10
IP_BLACKLIST = ["192.168.1.2", "127.0.0.1"]
class LimitMiddleware:
def __init__(self, get_response):
self.get_response = get_response
# One-time configuration and initialization.
def __call__(self, request):
# 处理请求前(url匹配前)调用
# Code to be executed for each request before
# the view (and later middleware) are called.
now = time.time()
print("处理请求前(url匹配前)调用",now)
request_queue = request.session.get("request_queue", [])
request_limit = request.session.get("request_limit", 0)
remot_addr = request.META.get("REMOTE_ADDR", "")
# 如果请求IP在黑名单中,那么始终拒绝访问
if remot_addr in IP_BLACKLIST:
return HttpResponse("您的IP已经被封,有问题请联系管理员")
# 如果请求被限制,那么请等待
if request_limit:
time.sleep(1)
visit_limit = now - request.session["request_queue"][-1]
if visit_limit >= request_limit:
request_limit = 0
visit_limit = 0
request.session["request_limit"] = request_limit
request.session["request_queue"] = []
return HttpResponse("%d秒后重试"%(request_limit - visit_limit))
if request_queue == []:
request_queue.append(now)
request.session["request_queue"] = request_queue
else:
request_queue.append(now)
request.session["request_queue"] = request_queue
# TIME_INTERVAL秒内访问超过VISIT_LIMIT次,则对其访问进行限制
if len(request_queue) >= VISIT_LIMIT:
if request_queue[0] - request_queue[-1] <= TIME_INTERVAL:
request.session["request_limit"] = RETRY_TIME
return HttpResponse("访问过快,%d秒后重试"%(RETRY_TIME))
else:
request_queue = []
request.session["request_queue"] = request_queue
response = self.get_response(request)
# 视图函数处理后,返回内容给浏览器前调用
# Code to be executed for each request/response after
# the view is called.
return response
# url匹配后视图函数处理前调用
def process_view(request, view_func, *view_args, **view_kwargs):
print("访问视图前:process_view")
# return HttpResponse("你还没访问到视图")
def process_exception(request, exception, *args):
print("服务器出错了....",*args)
return HttpResponse("服务器出错了....%")
- 配置 settings,应为用到了session技术,所以我们要把自已写的中间件那在django的session中间件后面,auth之前
MIDDLEWARE = [
'django.middleware.security.SecurityMiddleware',
'django.contrib.sessions.middleware.SessionMiddleware',
'django.middleware.common.CommonMiddleware',
'django.middleware.csrf.CsrfViewMiddleware',
"frequencylimit.frequencylimitmiddleware.LimitMiddleware",
'django.contrib.auth.middleware.AuthenticationMiddleware',
'django.contrib.messages.middleware.MessageMiddleware',
'django.middleware.clickjacking.XFrameOptionsMiddleware',
]