1. 程式人生 > >記一次《flask web 開發實戰》flask-login學習(不完全的小整理)

記一次《flask web 開發實戰》flask-login學習(不完全的小整理)

前景

主要問題

  • flask-login 的流程
  • session,cookie
  • remember_me這個功能

第一步–編寫使用者類

  • 使用者類需要包含四個方法
    用於表示使用者的類需要實現這些方法:

    • is_authenticated()
      當用戶通過驗證時,也即提供有效證明時返回 True 。(只有通過驗證的使用者 會滿足 login_required 的條件。)
    • is_active()
      如果這是一個活動使用者且通過驗證,賬戶也已啟用,未被停用,也不符合任何你 的應用拒絕一個賬號的條件,返回 True 。不活動的賬號可能不會登入(當然, 是在沒被強制的情況下)。
    • is_anonymous()
      如果是一個匿名使用者,返回 True 。(真實使用者應返回 False 。)
    • get_id()
      返回一個能唯一識別使用者的,並能用於從 user_loader 回撥中 載入使用者的 unicode 。注意著 必須 是一個 unicode ——如果 ID 原本是 一個 int 或其它型別,你需要把它轉換為 unicode 。

要簡便地實現使用者類,你可以從 UserMixin 繼承,它提供了對所有這些方法的預設 實現。(雖然這不是必須的。)

第二步-初始化LonginManager

login_manager = LoginManager()
login_manager.session_protection = 'strong'
login_manager.login_view = 'auth.login'

首先初始化一個物件,然後進行配置

session_protection

session_protection有三種模式:None,basic,strong

  • 用處:保護會話的,防止會話session被盜用,被啟用的時候在basic和strong兩種模式中執行預設為:basic
  • 讀一波原始碼
    def _session_protection(self):
        sess = session._get_current_object()
        ident = self._session_identifier_generator()

        app = current_app._get_current_object()
        mode = app.config.get('SESSION_PROTECTION'
, self.session_protection) # if the sess is empty, it's an anonymous user or just logged out # so we can skip this if sess and ident != sess.get('_id', None): if mode == 'basic' or sess.permanent: sess['_fresh'] = False session_protected.send(app) return False elif mode == 'strong': for k in SESSION_KEYS: sess.pop(k, None) sess['remember'] = 'clear' session_protected.send(app) return True return False

登入的時候,直接將user_id寫入session,session裡面有user_id就是登入的,並且標記這個使用者是新鮮的,就是通過登入的,而不是用的cookie。
在strong模式下,當之前瀏覽器關閉的時候,session裡面的內容都會刪除,只寫入一個remember欄位為clear,第二次登入時候

app.after_request(self._update_remember_cookie)
def _update_remember_cookie(self, response):
    # Don't modify the session unless there's something to do.
    if 'remember' in session:
        operation = session.pop('remember', None)
        if operation == 'set' and 'user_id' in session:
            self._set_cookie(response)
        elif operation == 'clear':
            self._clear_cookie(response)
    return response

首先session中的remember作為一個單獨的cookie寫入response,然後傳給前端,此時的remember欄位由於session中的remember已經被清除,寫上了clear,所以清楚了cookie,並傳給前端(怎麼不清除?改成basic模式,只顯示非fresh使用者,但是可以繼續用cookie)

  • 第一次登入
    這裡寫圖片描述
  • 關閉瀏覽器之後登入
    這裡寫圖片描述
  • 重新整理瀏覽器之後登入
    這裡寫圖片描述
    PS:圖片來自網上,過兩天附上自己實驗
    對於cookie的過期時間修改等,先留上線索,過兩天會用到
    這裡寫圖片描述

login_view

設定登入檢視的名稱,如果一個未登入使用者請求一個只有登入使用者才能訪問的檢視,則閃現一條錯誤訊息預設為

Please log in to access this page

並重定向到這裡設定的登入檢視。如果未設定登入檢視,則直接返回401錯誤。也可以自己設定錯誤訊息

login_manager.login_message = u"Bonvolu ensaluti por uzi tio paĝo."

第三步,回撥函式

@login_manager.user_loader
def load_user(user_id):
return User.query.get(int(user_id))

解讀:
在每次請求過來後,Flask-Login都會從Session中尋找”user_id”的值,如果找到的話,就會用這個”user_id”值來呼叫此回撥函式就是login_manager 中使用user_loader裝飾器設定的callback函式直接獲取當前登入的使用者,從會話中儲存的使用者 ID 重新載入使用者物件的資訊。然後返回到一開始的那個需要登入才能進入的介面。

第四步,登入使用者檢視函式login()部分

login_user(user, form.remember_me.data)

login_user() 函式的引數是要登入的使用者,以及可選的“記住我”布林值,“記住我”也在表單中填寫。如果值為 False ,那麼關閉瀏覽器後用戶會話就過期了,所以下次使用者訪問時要重新登入。如果值為 True ,那麼會在使用者瀏覽器中寫入一個長期有效的 cookie,使用這個 cookie 可以復現使用者會話。

return redirect(request.args.get('next') or url_for('main.index'))

使用者訪問未授權的 URL 時會顯示登入表單,Flask-Login會把原地址儲存在查詢字串的 next 引數中,這個引數可從 request.args 字典中讀取。如果查詢字串中沒有 next 引數,則重定向到首頁。

理解:這第一段的話好理解,第二段的意思是當訪問需要登入的介面page1時,成功完成登入之後,會設定完cookie,然後返回到之前需要登入才能訪問的介面page1,這個地址儲存在request.args字典裡面,沒有的話就回到首頁

總結

這次的最大最關鍵的問題還在cookie和session了,它們的原理,至今還未搞清,尤其是session的部分,之後還需要進一步作為深入。今天只是初步熟悉一下flask-login,過兩天要完成登入的介面,併成功完成上述待驗證的部分,特做此記錄。對於我這樣的小白來說,路還很長啊~最好的提升看來還是讀原始碼加上別人的講解。