關於 flask_session 在登入時設定後,再其他介面獲取時為None的問題

小天狼鑫發表於2024-05-07

flask本身的session對於生產來講可能並不能滿足我們,我們需要使用三方外掛來滿足我們的生產環境。

一般情況下,session對應的儲存值我們需要持久化到資料庫中,所以我們的session將會啟用flask三方外掛:flask_session

配置flask_session 由於每個專案的不同我的配置未必符合你的專案,你可以直接檢視flask_session的官方文件: Usage - Flask-Session 0.8.0 documentation

在settings裡面的配置

SESSION_TYPE = "redis"
SESSION_REDIS = Redis(
    host=REDIS_HOST, port=REDIS_PORT, password=REDIS_PASSWORD, db=REDIS_RESULTS_DB
)  # type: ignore
PERMANENT_SESSION_LIFETIME = dt.timedelta(minutes=5)
SESSION_COOKIE_DOMAIN = "*"

然後建立工廠函式等,以下是專案配置,我們可能並不相同

from flask_session import Session

session = Session()
from xxx.extensions import session
session.init_app(self.flask_app)

建立好後,我們在專案上使用一下

class Captcha(MethodView):

    def get(self):
        session["b64_str"] = “text”
        return json_response(data=b64_str)

class Captcha111(MethodView):

    def get(self):
        text = session.get("b64_str")
        print(text)
        return json_response(data=text)

當我們在呼叫captcha111的時候,你會發現session所get出來的資料是None。

這不符合我們對session的期望,這時我們需要知道為什麼會發生這種事。

解決問題的思路。

首先你需要知道,會不會是我們的redis資料庫的問題,我們先驗證資料是否是沒問題的。

我們把settings裡面的資料庫連線中,密碼修改為錯誤密碼,當我們呼叫captch路由時,會丟擲redis連線異常的錯誤,說明我們的redis連線是沒問題的,一般情況下,裡面所儲存的資料就也是沒問題的,我們應該這種自信,斷定redis是沒問題的。

既然redis是沒問題的,那就看在第二個路由裡面獲取時,走沒走redis資料庫,初步考慮應該是沒有的,不然不會取不出來,我們可以採取剛才的方式,將資料庫的密碼修改為錯誤,然後在呼叫獲取的方法,發現並未出現資料庫連線報錯,可見,當前的session在獲取資料時,並未連線資料庫,這就可以側面印證,在某一時刻,我們的session和上次的session並非是同一個session,哪怕這個session的id是相同的id。

這時,我們就需要知道flask_session的執行原理,否則我們無法得知它在哪個環節被限制住了:flask學習筆記--flask內建session處理機制_flask session httponly-CSDN部落格

當我們得知它會在

這裡進行相應的攔截時,我們可以考慮是不是因為我們使用postman二次訪問未攜帶相應的cookie導致的。

理論成立,實踐動手:

我們使用瀏覽器訪問後,取得cookie:

然後取出cookie後,我們是用postman發起訪問:

果然,data的資料出現,說明我們的想法是沒問題的。

那麼問題回到剛才,我們此時的session.get會訪問redis資料庫嗎?

答案是:會的。隨後我便驗證了,當密碼不正確時,程式碼執行到此處時會丟擲資料庫未連線的異常資訊。

最後,當你想讓它出現在cookie,以便前端直接訪問時:

你可以這樣寫:

class Captcha(MethodView):
    __doc__ = """獲取圖片驗證碼"""

    def get(self):
        from flask import Response
        b64_str, text = generate_captcha()
        session["b64_str"] = text
        response = json_response(code=CODE.OK.code, data=b64_str)
        response.set_cookie("session", session.sid)
        return response

相關文章