使用者登入過程設計以下步驟:
- 使用者
,eg: http://localhost:5000/auth/login。使用GET請求處理這個URL函數并傳回登入表單模闆。點選Login連結
-
使用者輸入使用者名和密碼,點選送出按鈕。再次調用相同處理函數,這次處理的是POST請求
a. 處理函數驗證通過表單送出的依據,然後調用
的Flask-login
login_user()
函數,登入函數
b.
login_user()
函數講使用者ID以字元串形式寫入使用者會話
c. 視圖函數重定向到指定的登入後跳轉頁面,例如首頁
-
浏覽器收到重定向響應,請求頁面
a. 調用首頁視圖函數, 渲染Jinjia2 模闆
b. 渲染過程中,首次出現
的Flask-login
current_user
的引用
c. 這個請求還沒有給上下文變量
指派,是以調用current_user
内部的Flask-login
函數,找出使用者是誰。_get_user()
def _get_user(): #首先需要知道請求上下文,代碼中的_request_ctx_stack.top中是否有user這個變量, # 如果沒有則_load_user if has_request_context() and not hasattr(_request_ctx_stack.top, 'user'): current_app.login_manager._load_user() return getattr(_request_ctx_stack.top, 'user', None)
d.def reload_user(self, user=None): ctx = _request_ctx_stack.top if user is None: user_id = session.get('user_id') if user_id is None: ctx.user = self.anonymous_user() else: if self.user_callback is None: raise Exception( "No user_loader has been installed for this " "LoginManager. Add one with the " "'LoginManager.user_loader' decorator.") user = self.user_callback(user_id) if user is None: ctx.user = self.anonymous_user() else: ctx.user = user else: ctx.user = user
函數檢查使用者會話中有沒有使用者ID,如果沒有,傳回一個_get_user()
的Flask-login
執行個體。如果有ID,調用AnonymousUser
user_loader
裝飾器注冊的函數,傳入使用者ID。
e. 應用中的
處理函數從資料庫讀取使用者,将其傳回。user_loader
把傳回的使用者對象指派給目前請求的Flask-login
current_user
上下文變量。
f. 模闆接受新指派的
current_user
使用
login_required
裝飾器裝飾的函數将使用
current_user
上下文變量判斷
current_user.is_authenticated
表達式的結果是否為True。相對的
logout_user
函數就簡單了,直接從使用者會話中把使用者ID删除
摘抄自《Flask Web開發》的8.4.6小節