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