全局对象session解析

接下来我们来看看flask的session对象,session对象也来自与globals.py文件,现贴出session对象的产生逻辑的源码:

from functools import partial

from werkzeug.local import LocalProxy
from werkzeug.local import LocalStack

def _lookup_req_object(name):
    top = _request_ctx_stack.top
    if top is None:
        raise RuntimeError(_request_ctx_err_msg)
    return getattr(top, name)


_request_ctx_stack = LocalStack()

session = LocalProxy(partial(_lookup_req_object, "session"))

LocalProxy(partial(_lookup_req_object, "session"))可知,session来自request上下文的session属性,接下来看一下session的具体处理逻辑和生命周期:

class Flask(_PackageBoundObject):
    def wsgi_app(self, environ, start_response):

        ctx = self.request_context(environ)
        error = None
        try:
            try:
                ctx.push()
                response = self.full_dispatch_request()
            except Exception as e:
                error = e
                response = self.handle_exception(e)
            except:  # noqa: B001
                error = sys.exc_info()[1]
                raise
            return response(environ, start_response)
        finally:
            if self.should_ignore_error(error):
                error = None
            ctx.auto_pop(error)

我们回忆下reqeust上下文的实例化逻辑,来找寻session的踪迹:

由代码可知RequestContext实例化时,对session进行初始化,默认为None,而后在push方法中,针对不同的session值,进行不同的处理。接下来具体的分析一下: 如果session为None时,将其值赋为session_interface.open_session的返回值,session_interfaceself.app.session_interface, 即Flask类的session_interface,默认为flask.sessions.SecureCookieSessionInterface的实例化对象,那flask.sessions.SecureCookieSessionInterface的实现原理如何,我们从源码中发现秘密:

SecureCookieSessionInterface.open_session方法中,首先获取序列化实例s,由get_signing_serializer可知,当Flask的SECRET_KEY为None, s值也为None,open_session直接返回None,否则继续获取request的cookies,cookies的key为app.session_cookie_name, 默认值为session,翻看Flask的源码,发现这里使用的是python的数据描述符类,关于此概念可以自行百度,才能具体理解此处的妙用。最后返回self.session_class实例化对象,self.session_class默认为session.py中的SecureCookieSession类。 继续看当self.session为None时,将会重新赋值为session_interface.make_null_session(self.app),我们看一下make_null_session的具体实现: 需要注意的是SecureCookieSessionInterface中并未发现make_null_session方法,但是在父类SessionInterface中实现了此方法,下面看一下具体的代码:

看代码的实现方式,当Flask的配置SECRET_KEY为None,session将会是不可用。默认为NullSession的实例,此对象将不能进行任何操作。当我们启用session时,即SECRET_KEY不为None,此时我们的session将在response返回给客户端是进行save_session操作,即下面的逻辑:

可以看到我们对cookie的修改将会在cookie未过期之前一直保留,并通过itsdangerous库进行序列化和反序列化。至此session的基本逻辑已介绍完毕,具体的代码还需要我仔细去读才能理解。

Last updated

Was this helpful?