1. 程式人生 > >Python-Flask裝飾器實現使用者認證登入功能(登入限制)

Python-Flask裝飾器實現使用者認證登入功能(登入限制)

 

當我們開發某個網站的時候,肯定會有使用者登入和註冊的功能,我們寫好網頁的時候,要是沒有認證,知道路由就能訪問資源(或者不想沒有登入就讓使用者使用某個功能),使用者登入的資訊都是在cook裡面,需要認證就去cook裡面取值判斷是否有該使用者,當用戶沒有登入就去訪問資源路由時,就拒絕訪問,並自動跳轉到登入頁面...

最近在學flask,python裡面有個強大的利器,生成器yield和裝飾器@函式名,flask也用裝飾器作路由,直接進入正題...

裝飾器實際上就是一個函式,有兩個特別之處:

  1. 引數是一個函式
  2. 返回值也是一個函式

先說下裝飾器,舉個栗子:

現在有某個需求: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")

,然後執行 func()函式,func就是傳進去的run函式,就會答應run。也就實現了所有函式之前列印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('/路由名')形成的路由,一個網站有很多路由,登入路由,註冊路由,首頁展示路由....當用戶使用其他路由的時而沒有登入的時候,我們就自動跳轉到登入頁面去。