1. 程式人生 > >django-基於中介軟體實現限制ip頻繁訪問

django-基於中介軟體實現限制ip頻繁訪問

########django-基於中介軟體寫一個限制頻繁登陸########

額額,標題已經很醒目了,通過中介軟體去實現,其他方法也可以實現

瀏覽器前端傳來的請求,必須通過中介軟體,才能到後面路由,檢視函式,所以我們在中介軟體那裡做一層處理,
我們還需要知道是哪個ip,在什麼時候,請求了幾次,這些資料是要知道,並且記錄下來,所以我建立了一個
表,來存放這些資訊資料

models檔案:
    class Host_info(models.Model):
        host = models.CharField(max_length=32)
        count = models.IntegerField()
        start_time 
= models.DateTimeField() is_lock = models.CharField(max_length=32,default='2') host:記錄主機ip count:記錄請求的次數 start_time:記錄請求的時間 is_lock:記錄該ip的狀態,預設為2 2代表未鎖定,1代表鎖定 接下來就是自定義中介軟體了,並寫process_request方法,我們只對請求做處理,我先貼程式碼,最後寫我遇到的一些問題 mymiddleware檔案(我自定義的中介軟體): from django.utils.deprecation import
MiddlewareMixin from django.shortcuts import render, HttpResponse from app01 import models import datetime class Md1(MiddlewareMixin): def process_request(self, request): url = request.path if url.startswith('/favicon.ico'): return HttpResponse
class Md2(MiddlewareMixin): def process_request(self, request): now_time = datetime.datetime.now() host = request.META.get('REMOTE_ADDR') ret = models.Host_info.objects.filter(host=host).first() if ret: aa = now_time - ret.start_time if aa.seconds >= 60: ret.count = 1 ret.start_time = now_time ret.is_lock = '2' ret.save() return None if aa.seconds < 60 and ret.is_lock == '1': return HttpResponse('登陸次數頻繁,一分鐘後再試') if ret.count < 4 and ret.is_lock == '2': if ret.count == 2: ret.is_lock = '1' ret.count = 0 ret.save() else: ret.count += 1 ret.start_time = now_time ret.save() return None else: models.Host_info.objects.create(host=host, start_time=now_time, count=1) return None settings檔案: 新增兩行程式碼在MIDDLEWARE列表中: 'mymiddleware.Md1', 'mymiddleware.Md2', 並配置下面兩句,原因後面會說 TIME_ZONE = 'Asia/Shanghai' USE_TZ = False 遇到兩個問題: 問題一:就是datetime,也就是時間分割槽問題,因為我資料表中需要儲存到該ip訪問的時間,存的時候存的是datetime物件 ,但是我從資料庫中取出來這個時間,進行比較會報出錯誤,錯誤型別忘記了,我就列印了從資料庫中取出的時間資料, 發現,這個時間帶著時區,而我datetime.datetime.now()的時間是本機時間,根本不能相減,相比較。網上收索才 知道django預設是有時間分割槽的,TIME_ZONE = 'UTC',USE_TZ = True,這兩句。 解決方式:在setting檔案中將上面那兩句修改為TIME_ZONE = 'Asia/Shanghai',USE_TZ = False。這樣就解決了。 在django中但凡出現時間的話,這個地方需要注意下。 問題二:額額這個問題,我在寫的時候出現過,但是今天測試沒那個問題,反正寫上吧。我之前的錯誤就是我發出一個請求,首先 第一個請求就是訪問到url,接著第二個請求就是發出favicon.ico這種類似的,請求ico這個。以這個情況來說問題吧, 你雖然在瀏覽器只發出一個請求,但是響應過來的網頁,裡面可以還有其他請求,所以這中情況需要考慮到。 解決方式:我在對使用者ip做限制之前,加一箇中間件,過濾掉其它的請求。,也就是上面的MD1。 ## 程式碼其實很簡單,主要是邏輯處理,你是怎麼想就用程式碼去實現。 ## 對了,這裡的資料儲存,你可以定義一個變數去存放存這些資訊(也就是我資料表存放的這個) ## 這裡唯一值得注意的就是時間了,你要很清楚知道時區這個問題。 補充一點,datetime的一個用法 例子中我用到datetime物件之間相減,取差多少秒,也就是這句 aa = now_time - ret.start_time aa.seconds # 取到相差多少秒 這裡的aa是datetime.timedelta型別