Python-Flask裝飾器實現使用者認證登入功能(登入限制)
當我們開發某個網站的時候,肯定會有使用者登入和註冊的功能,我們寫好網頁的時候,要是沒有認證,知道路由就能訪問資源(或者不想沒有登入就讓使用者使用某個功能),使用者登入的資訊都是在cook裡面,需要認證就去cook裡面取值判斷是否有該使用者,當用戶沒有登入就去訪問資源路由時,就拒絕訪問,並自動跳轉到登入頁面...
最近在學flask,python裡面有個強大的利器,生成器yield和裝飾器@函式名,flask也用裝飾器作路由,直接進入正題...
裝飾器實際上就是一個函式,有兩個特別之處:
- 引數是一個函式
- 返回值也是一個函式
先說下裝飾器,舉個栗子:
現在有某個需求:1.在列印run之前,要先列印一個Hello world 2.在所有函式執行之前,都要列印一個hello world。
我們可以向下面這種在每個函式裡面加入print("hello world"),加入有幾千個函式,一個個的加print("hello world"),不太現實!,如果某天又要列印其他的東西,又要一個一個修改,心態會爆炸的...
所以就不得不說裝飾器的強大,能夠一次給所有函式增加功能.
定一個函式:my_log,裝飾器引數是一個函式,就隨便寫個形參。
def my_log(func):
在定義一個函式在my_log裡面,作為返回值的函式,def wrapper(), 返回一個函式體。
def my_log(func):
def wrapper():
print("hello world")
func()
return wrapper
@my_log # 把my_log函式作為裝飾器
def run():
print("run")
#執行run函式
run()
在解釋一下上面的意思:等效於 run=my_log(run),1.裝飾器器會先把run函式參進去my_log(run),2.然後返回的結果給run函式。run=my_log(run)。然後執行my_log函式,就先執行print("hello world")
以後只要有函式要實現這個功能,我們就在函式名上一行加裝飾器函式,@my_log,就ok了。
大概瞭解裝飾器後然後進入真正的主題:使用者登入認證(登入限制):
定義一個登入的裝飾器函式:def login_requir()
保留一個源資訊,用到wraps,把原函式名保留下來,使用之前的匯入庫:
from functools import wraps
def login_requir(func):
@wraps(func)#保留源資訊,本質是endpoint裝飾,否則修改函式名很危險
def inner(*args,**kwargs):#接收引數,*args接收多餘引數形成元組,**kwargs接收對於引數形成字典
user=session.get('user_id') #表單接手網頁中登入資訊,存入到session中,判斷使用者是否登入
if not user:
return redirect('/login') #沒有登入就跳轉到登入路由下
return func(*args,**kwargs)#登入成功就執行傳過來的函式
return inner
在每個需要判斷使用者登入之前都加入裝飾器@login_requir,就能限制登入了...
再說下更好理解的裝飾器:
@app.before_request#執行所有裝飾器都要執行當前裝飾器(簡潔版實現同樣功能)
def login_required():
if request.path in ['/login','/register']: #如果登入的路由是註冊和登入就返會none
return None
user=session.get('user_id') #獲取使用者登入資訊
if not user: #沒有登入就自動跳轉到登入頁面去
return redirect('/login')
return None
上面的程式碼同樣實現使用者認證功能(登入限制),因為flask裡面每個路由都是裝飾器@app.route('/路由名')形成的路由,一個網站有很多路由,登入路由,註冊路由,首頁展示路由....當用戶使用其他路由的時而沒有登入的時候,我們就自動跳轉到登入頁面去。