使用 flask-login 擴充套件
實現授權系統的一種更簡單的方法是使用 flask-login 擴充套件。該專案的網站包含一個詳細而精心編寫的快速入門,本例中提供了較短版本。
大概的概念
該擴充套件公開了一組用於以下的函式:
- 記錄使用者
- 記錄使用者
- 檢查使用者是否登入,並找出哪個使用者
什麼不做,你自己要做什麼:
- 沒有提供儲存使用者的方法,例如在資料庫中
- 沒有提供檢查使用者憑據的方法,例如使用者名稱和密碼
下面是一整套工作所需的最小步驟。
我建議將所有與 auth 相關的程式碼放在單獨的模組或包中,例如 auth.py
。這樣,你可以單獨建立必要的類,物件或自定義函式
建立一個 LoginManager
擴充套件使用 LoginManager
類,必須在 Flask
應用程式物件上註冊。
from flask_login import LoginManager
login_manager = LoginManager()
login_manager.init_app(app) # app is a Flask object
如前所述,LoginManager
例如可以是單獨檔案或包中的全域性變數。然後可以將其匯入到建立 Flask
物件的檔案中或在應用程式工廠函式中進行初始化。
指定用於載入使用者的回撥
通常會從資料庫載入使用者。回撥必須返回一個物件,該物件表示與提供的 ID 相對應的使用者。如果 ID 無效,則應返回 None
。
@login_manager.user_loader
def load_user(user_id):
return User.get(user_id) # Fetch the user from the database
這可以在建立你的 LoginManager
之後直接完成。
代表你的使用者的類
如上所述,user_loader
回撥必須返回代表使用者的物件。這究竟是什麼意思?例如,該物件可以是儲存在資料庫中的使用者物件的包裝器,也可以是資料庫中直接的模型。該物件必須實現以下方法和屬性。這意味著如果回撥返回資料庫模型,則需要確保將所提及的屬性和方法新增到模型中。
-
is_authenticated
如果使用者已通過身份驗證,則此屬性應返回
True
,即他們已提供有效憑據。你需要確保user_loader
回撥返回的代表你的使用者的物件返回該方法的True
。 -
is_active
如果這是一個活躍使用者,則此屬性應返回 True - 除了經過身份驗證之外,他們還啟用了帳戶,未被暫停,或者你的應用程式拒絕帳戶的任何條件。非活動帳戶可能無法登入。如果你沒有此類機制,請從此方法返回
True
。 -
is_anonymous
如果這是匿名使用者,則此屬性應返回 True。這意味著
user_loader
回撥返回的使用者物件應返回True
。 -
get_id()
此方法必須返回唯一標識此使用者的 unicode,並且可用於從
user_loader
回撥載入使用者。請注意,這必須是 unicode - 如果 ID 本身是 int 或其他型別,則需要將其轉換為 unicode。如果user_loader
回撥從資料庫返回物件,則此方法很可能返回此特定使用者的資料庫 ID。相同的 ID 當然應該導致user_loader
回撥稍後返回同一個使用者。
如果你想使事情變得更容易為自己(**它實際上是推薦),你可以繼承 UserMixin
由 user_loader
回撥(大概資料庫模型)返回的物件。你可以在此處檢視預設情況下如何實現這些方法和屬性。
記錄使用者
該擴充套件程式將驗證使用者輸入的使用者名稱和密碼。事實上,如果你使用使用者名稱和密碼組合或其他機制,擴充套件程式並不在意。這是使用使用者名稱和密碼記錄使用者的示例。
@app.route('/login', methods=['GET', 'POST'])
def login():
# Here we use a class of some kind to represent and validate our
# client-side form data. For example, WTForms is a library that will
# handle this for us, and we use a custom LoginForm to validate.
form = LoginForm()
if form.validate_on_submit():
# Login and validate the user.
# user should be an instance of your `User` class
login_user(user)
flask.flash('Logged in successfully.')
next = flask.request.args.get('next')
# is_safe_url should check if the url is safe for redirects.
# See http://flask.pocoo.org/snippets/62/ for an example.
if not is_safe_url(next):
return flask.abort(400)
return flask.redirect(next or flask.url_for('index'))
return flask.render_template('login.html', form=form)
通常,日誌記錄使用者是通過呼叫 login_user 並將表示前面提到的使用者的物件例項傳遞給它來完成的。如圖所示,這通常發生在從資料庫中檢索使用者並驗證其憑據之後,但是在此示例中,使用者物件只是神奇地出現。
我已登入使用者,現在怎麼辦?
user_loader
回撥返回的物件可以通過多種方式訪問。
-
在模板中:
擴充套件使用模板上下文處理器以名稱
current_user
自動注入它。要禁用該行為,請在LoginManager
建構函式中使用自定義處理器集add_context_processor=False
。{% if current_user.is_authenticated %} Hi {{ current_user.name }}! {% endif %}
-
在 Python 程式碼中:
擴充套件提供了一個名為
current_user
的請求繫結物件。from flask_login import current_user @app.route("/hello") def hello(): # Assuming that there is a name property on your user object # returned by the callback if current_user.is_authenticated: return 'Hello %s!' % current_user.name else: return 'You are not logged in!'
-
使用裝飾器快速限制訪問
login_required
裝飾器可用於快速限制訪問。from flask_login import login_required @app.route("/settings") @login_required def settings(): pass
記錄使用者
使用者可以通過呼叫 logout_user()
登出 。即使使用者沒有登入也似乎是安全的,因此 @login_required
裝飾器很可能被省略。
@app.route("/logout")
@login_required
def logout():
logout_user()
return redirect(somewhere)
如果使用者未登入並訪問 current_user
物件會發生什麼?
通過 defult 返回 AnonymousUserMixin :
is_active
和is_authenticated
是False
is_anonymous
是True
get_id()
返回None
要為匿名使用者使用不同的物件,請提供一個可呼叫的(類或工廠函式),為你的 LoginManager
建立匿名使用者:
login_manager.anonymous_user = MyAnonymousUser
接下來是什麼?
以上是對擴充套件的基本介紹。要了解有關配置和其他選項的更多資訊,強烈建議你閱讀官方指南 。