由於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',
]