django 基于中間件實(shí)現(xiàn)限制ip頻繁訪問過程詳解
額額,標(biāo)題已經(jīng)很醒目了,通過中間件去實(shí)現(xiàn),其他方法也可以實(shí)現(xiàn)
瀏覽器前端傳來的請(qǐng)求,必須通過中間件,才能到后面路由,視圖函數(shù),所以我們?cè)谥虚g件那里做一層處理,我們還需要知道是哪個(gè)ip,在什么時(shí)候,請(qǐng)求了幾次,這些數(shù)據(jù)是要知道,并且記錄下來,所以我創(chuàng)建了一個(gè)表,來存放這些信息數(shù)據(jù)
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:記錄主機(jī)ip
count:記錄請(qǐng)求的次數(shù)
start_time:記錄請(qǐng)求的時(shí)間
is_lock:記錄該ip的狀態(tài),默認(rèn)為2 2代表未鎖定,1代表鎖定
接下來就是自定義中間件了,并寫process_request方法,我們只對(duì)請(qǐng)求做處理,我先貼代碼,最后寫我遇到的一些問題
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('登陸次數(shù)頻繁,一分鐘后再試') 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',
并配置下面兩句,原因后面會(huì)說
TIME_ZONE = 'Asia/Shanghai' USE_TZ = False
遇到兩個(gè)問題:
問題一:就是datetime,也就是時(shí)間分區(qū)問題,因?yàn)槲覕?shù)據(jù)表中需要保存到該ip訪問的時(shí)間,存的時(shí)候存的是datetime對(duì)象,但是我從數(shù)據(jù)庫中取出來這個(gè)時(shí)間,進(jìn)行比較會(huì)報(bào)出錯(cuò)誤,錯(cuò)誤類型忘記了,我就打印了從數(shù)據(jù)庫中取出的時(shí)間數(shù)據(jù), 發(fā)現(xiàn),這個(gè)時(shí)間帶著時(shí)區(qū),而我datetime.datetime.now()的時(shí)間是本機(jī)時(shí)間,根本不能相減,相比較。
網(wǎng)上收索才 知道django默認(rèn)是有時(shí)間分區(qū)的,TIME_ZONE = 'UTC',USE_TZ = True,這兩句。
解決方式:在setting文件中將上面那兩句修改為TIME_ZONE = 'Asia/Shanghai',USE_TZ = False。這樣就解決了。
在django中但凡出現(xiàn)時(shí)間的話,這個(gè)地方需要注意下。
問題二:額額這個(gè)問題,我在寫的時(shí)候出現(xiàn)過,但是今天測(cè)試沒那個(gè)問題,反正寫上吧。我之前的錯(cuò)誤就是我發(fā)出一個(gè)請(qǐng)求,
首先
第一個(gè)請(qǐng)求就是訪問到url,接著第二個(gè)請(qǐng)求就是發(fā)出favicon.ico這種類似的,請(qǐng)求ico這個(gè)。以這個(gè)情況來說問題吧,
你雖然在瀏覽器只發(fā)出一個(gè)請(qǐng)求,但是響應(yīng)過來的網(wǎng)頁,里面可以還有其他請(qǐng)求,所以這中情況需要考慮到。
解決方式:我在對(duì)用戶ip做限制之前,加一個(gè)中間件,過濾掉其它的請(qǐng)求。,也就是上面的MD1。
## 代碼其實(shí)很簡單,主要是邏輯處理,你是怎么想就用代碼去實(shí)現(xiàn)。 ## 對(duì)了,這里的數(shù)據(jù)存儲(chǔ),你可以定義一個(gè)變量去存放存這些信息(也就是我數(shù)據(jù)表存放的這個(gè)) ## 這里唯一值得注意的就是時(shí)間了,你要很清楚知道時(shí)區(qū)這個(gè)問題。
補(bǔ)充一點(diǎn),datetime的一個(gè)用法
例子中我用到datetime對(duì)象之間相減,取差多少秒,也就是這句
aa = now_time - ret.start_time aa.seconds # 取到相差多少秒
這里的aa是datetime.timedelta類型
以上就是本文的全部內(nèi)容,希望對(duì)大家的學(xué)習(xí)有所幫助,也希望大家多多支持腳本之家。
相關(guān)文章
Python中的文件和目錄操作實(shí)現(xiàn)代碼
對(duì)于文件和目錄的處理,雖然可以通過操作系統(tǒng)命令來完成,但是Python語言為了便于開發(fā)人員以編程的方式處理相關(guān)工作,提供了許多處理文件和目錄的內(nèi)置函數(shù)。重要的是,這些函數(shù)無論是在Unix、Windows還是Macintosh平臺(tái)上,它們的使用方式是完全一致的。2011-03-03python可擴(kuò)展的Blender 3D插件開發(fā)匯總
這篇文章主要為大家介紹了python可擴(kuò)展的Blender 3D插件開發(fā)匯總,有需要的朋友可以借鑒參考下,希望能夠有所幫助,祝大家多多進(jìn)步,早日升職加薪2023-09-09Python刪除列表中多個(gè)元素的四種方法總結(jié)
這篇文章主要給大家介紹了關(guān)于Python刪除列表中多個(gè)元素的四種方法,在Python中想要?jiǎng)h除列表的某個(gè)元素,可以使用本文介紹的方法,文中通過代碼介紹的非常詳細(xì),需要的朋友可以參考下2023-09-09在Python中字典根據(jù)多項(xiàng)規(guī)則排序的方法
今天小編就為大家分享一篇在Python中字典根據(jù)多項(xiàng)規(guī)則排序的方法,具有很好的參考價(jià)值,希望對(duì)大家有所幫助。一起跟隨小編過來看看吧2019-01-01Python文本情感分類識(shí)別基于SVM算法Django框架實(shí)現(xiàn)
這篇文章主要為大家介紹了Python文本情感分類識(shí)別基于SVM算法Django框架實(shí)現(xiàn)詳解,有需要的朋友可以借鑒參考下,希望能夠有所幫助,祝大家多多進(jìn)步,早日升職加薪2023-07-07Python使用random模塊生成隨機(jī)數(shù)操作實(shí)例詳解
這篇文章主要介紹了Python使用random模塊生成隨機(jī)數(shù)操作,結(jié)合具體實(shí)例形式詳細(xì)分析了random模塊生成隨機(jī)數(shù)的各種常用技巧與相關(guān)操作注意事項(xiàng),需要的朋友可以參考下2019-09-09