Django自帶的Admin很好用,但是放到生產環境總還差了點什麼= =
看看admin的介紹:
Django奉行Python的內建電池哲學。它自帶了一系列在Web開發中用於解決常見問題或需求的額外的、可選工具。這些工具和外掛,例如django.contrib.redirects都必須在settings中的INSTALLED_APPS處進行註冊,有的還需要執行manage.py migrate命令,在資料庫中建立一些資料表。
Admin站點是Django有別於其它Web框架最重要的一點,並且非常受歡迎,簡直是出門旅遊xxxx的必備。不管你是寫個小demo還是做個大專案都用得上。admin(下文中將Admin管理後臺簡稱為admin)通過讀取你的模型資料,快速構造出一個可以對實際資料進行管理的Web站點,常用於開發測試,簡單管理等場合,適用於部門內部為工作方便的場合,但不建議在生產環境中使用。
為什麼不建議在生產環境使用呢,因為Admin缺了驗證碼和登入限制這種安全方面的功能!等會被人隨便暴力破解就進後臺了,那我們的系統安全性還怎麼保障?
但是別急,我已經通過魔改的方式實現了驗證碼和登入限制了,現在可以愉快使用admin系統了。
先看看效果
效果還是nice的,登入嘗試次數可以自己設定,我這裡就不演示了,輸那麼多次錯誤密碼太麻煩了。
驗證碼
驗證碼我是用了django-simple-captcha
這個庫,配合multi_captcha_admin
來生成驗證碼form,非常方便。
首先是pip安裝這兩個庫,大家都懂的,不再贅述。
配置一下 settings.py
:
INSTALLED_APPS = [
'multi_captcha_admin',
]
# 驗證碼配置
MULTI_CAPTCHA_ADMIN = {
'engine': 'simple-captcha',
}
配置 urls.py
:
# 新增這一項
path('captcha/', include('captcha.urls')),
到了這步就好啦,如果用的是Django官方的Admin就直接能顯示出登入的驗證碼了,不過我用的是第三方的Admin,所以需要手動新增form。
方法很簡單,找到login.html
,在登入的表單裡面新增這一項就好了。
{{ form.captcha }}
預設生成的驗證碼和輸入框是原生樣式,比較醜~ 我們可以優化一下。我是用js把生成的圖片和驗證碼輸入框替換成elementUI的樣式,有需要的小夥伴可以參考一下。
var row = document.querySelector('#captcha_group');
var captcha_img = document.querySelector('img.captcha');
var col_8 = document.createElement('el-col');
col_8.setAttribute(':span', '8');
col_8.appendChild(captcha_img);
var captcha_input = document.querySelector('#id_captcha_1');
var el_input = document.createElement('el-input');
var col_16 = document.createElement('el-col');
col_16.setAttribute(':span', '16');
el_input.setAttribute('name', captcha_input.getAttribute('name'));
el_input.setAttribute('v-model', 'captcha');
el_input.setAttribute('required', 'required');
el_input.setAttribute('placeholder', '請輸入驗證碼');
col_16.appendChild(el_input);
captcha_input.parentNode.removeChild(captcha_input);
row.appendChild(col_8);
row.appendChild(col_16);
登入限流
這個也不復雜,不過我一開始做還是花了比較長時間,查不到什麼有用的資料,後面我去讀了Django Admin的程式碼,一下就想出解決方法了哈哈~
通過admin的程式碼,我發現處理登入是admin.site.login(request, extra_context)
這個方法,那問題就變得很簡單了,給他加一個裝飾器就好了,不過我們不能去修改框架的程式碼,所以自己寫一個新的view,如下:
# 覆蓋預設的admin登入方法實現登入限流
@ratelimit(key='ip', rate='5/m', block=True)
def extend_admin_login(request, extra_context=None):
return admin.site.login(request, extra_context)
然後在urls.py
裡配置一下,記得要放在admin
的前面:
urlpatterns = [
path('admin/login/', views.extend_admin_login),
path('admin/', admin.site.urls),
]
這樣就可以實現限流了,這裡要介紹一下ratelimit
這個裝飾器,這是django-ratelimit這個包提供的,為了使用這個包,需要配置redis快取,附上配置程式碼:
# 配置redis快取
CACHES = {
'default': {
'BACKEND': 'django_redis.cache.RedisCache', # 快取後端 Redis
# 連線Redis資料庫(伺服器地址)
# 一主帶多從(可以配置個Redis,寫走第一臺,讀走其他的機器)
'LOCATION': [
'redis://localhost:6379/0',
],
'KEY_PREFIX': 'milky', # 專案名當做檔案字首
'OPTIONS': {
'CLIENT_CLASS': 'django_redis.client.DefaultClient', # 連線選項(預設,不改)
'CONNECTION_POOL_KWARGS': {
'max_connections': 512, # 連線池的連線(最大連線)
},
}
}
}
@ratelimit(key='ip', rate='5/m', block=True)
,key=ip
表示根據ip來區分,rate=5/m
表示一分鐘最多請求這個介面5次,block=true
表示超過這個限制就直接攔截,如果沒有設定block引數的話,超過限制也不會攔截,但是可以在ratelimit計數器裡面看到請求的次數。
更多用法可以看官方文件:https://django-ratelimit.readthedocs.io/en/stable/index.html
參考資料
- https://github.com/a-roomana/django-multi-captcha-admin
- https://django-simple-captcha.readthedocs.io/en/latest/advanced.html#rendering
歡迎交流
我整理了一系列的技術文章和資料,在公眾號「程式設計實驗室」後臺回覆 linux、flutter、c#、netcore、android、java、python 等可獲取相關技術文章和資料,同時有任何問題都可以在公眾號後臺留言~