Flask中session源码执行过程

Posted chenjunkan

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了Flask中session源码执行过程相关的知识,希望对你有一定的参考价值。

1.面向对象补充知识metaclass

创建类就可以有两种方式:

a.普通方式

技术分享图片
1 class Foo(object):
2  
3     def func(self):
4         print hello wupeiqi
View Code

b.特殊方式(type类的构造函数)

技术分享图片
1 def func(self):
2     print hello wupeiqi
3  
4 Foo = type(Foo,(object,), {func: func})
5 #type第一个参数:类名
6 #type第二个参数:当前类的基类
7 #type第三个参数:类的成员
View Code

c.metaclass代码示例

技术分享图片
 1 class MyType(type):
 2     def __init__(self,*args,**kwargs):
 3         print(init)
 4         super(MyType,self).__init__(*args,**kwargs)
 5 
 6     def __call__(self, *args, **kwargs):
 7         print(call本质:调用类的__new__,再调用类的__init__)
 8         return super(MyType,self).__call__( *args, **kwargs)
 9 
10 
11 class Foo(metaclass=MyType):
12     pass
13 
14 class Bar(Foo):
15     pass
16 
17 obj = Bar()
View Code

2.session源码分析

技术分享图片
 1 请求到来:
 2 1.app.__call__-->app.wsgi_app-->ctx.push();此时在threadinglocal中有ctx.app,ctx.request,ctx.session[],其中session中是没有值的
 3 2.self.session = session_interface.open_session(self.app,self.request)
 4 说明:
 5 1.session_interface = SecureCookieSessionInterface(),因此self.session = SecureCookieSessionInterface()
 6 2.执行open_session
 7     def open_session(self, app, request):
 8         s = self.get_signing_serializer(app)
 9         if s is None:
10             return None
11         val = request.cookies.get(app.session_cookie_name)
12         if not val:
13             return self.session_class()
14         max_age = total_seconds(app.permanent_session_lifetime)
15         try:
16             data = s.loads(val, max_age=max_age)
17             return self.session_class(data)
18         except BadSignature:
19             return self.session_class()
20 3.session_class其实是一个特殊的dict对象
21 a.session_class = SecureCookieSession
22 b.class SecureCookieSession(CallbackDict, SessionMixin):
23 c.class CallbackDict(UpdateDictMixin, dict):
24 d.class dict(object):
25 
26 4.在请求结束后就会执行save_session
27     def save_session(self, app, session, response):
28         domain = self.get_cookie_domain(app)
29         path = self.get_cookie_path(app)
30 
31         if session.accessed:
32             response.vary.add(Cookie)
33 
34         if not self.should_set_cookie(app, session):
35             return
36 
37         httponly = self.get_cookie_httponly(app)
38         secure = self.get_cookie_secure(app)
39         samesite = self.get_cookie_samesite(app)
40         expires = self.get_expiration_time(app, session)
41         val = self.get_signing_serializer(app).dumps(dict(session))
42         response.set_cookie(
43             app.session_cookie_name,
44             val,
45             expires=expires,
46             httponly=httponly,
47             domain=domain,
48             path=path,
49             secure=secure,
50             samesite=samesite
51         )
View Code

3.自定义MySessionInterFace

技术分享图片
 1 from flask import Flask,session
 2 
 3 
 4 app = Flask(__name__)
 5 app.secret_key = suijksdfsd
 6 
 7 
 8 import json
 9 class MySessionInterFace(object):
10     def open_session(self,app,request):
11         return {}
12 
13     def save_session(self, app, session, response):
14         response.set_cookie(session_idfsdfsdfsdf,json.dumps(session))
15 
16     def is_null_session(self, obj):
17         """Checks if a given object is a null session.  Null sessions are
18         not asked to be saved.
19 
20         This checks if the object is an instance of :attr:`null_session_class`
21         by default.
22         """
23         return False
24 
25 app.session_interface = MySessionInterFace()
26 
27 @app.route(/)
28 def index():
29     # 特殊空字典
30     # 在local的ctx中找到session
31     # 在空字典中写值
32     # 在空字典中获取值
33     session[xxx] = 123
34 
35 
36     return Index
37 
38 # # 一旦请求到来
39 app.__call__
40 app.wsgi_app
41 app.session_interface
42 app.open_session
43 
44 
45 if __name__ == __main__:
46 
47     app.run()
View Code

4.使用flask_session

技术分享图片
  1 from flask import Flask, session
  2 
  3 app = Flask(__name__)
  4 app.secret_key = suijksdfsd
  5 
  6 #
  7 from redis import Redis
  8 from flask_session import RedisSessionInterface
  9 
 10 conn = Redis()
 11 app.session_interface = RedisSessionInterface(conn, key_prefix=__, use_signer=False, permanent=True)
 12 
 13 from redis import Redis
 14 from flask.ext.session import Session
 15 
 16 app.config[SESSION_TYPE] = redis
 17 app.config[SESSION_REDIS] = Redis(host=192.168.0.94, port=6379)
 18 Session(app)
 19 
 20 
 21 @app.route(/)
 22 def index():
 23     session[xxx] = 123
 24     return Index
 25 
 26 
 27 if __name__ == __main__:
 28     app.run()
 29 
 30 说明:使用session必须要有secret_key 
 31 
 32 源码说明:实际上RedisSessionInterface是继承SessionInterface
 33 app.session_interface = RedisSessionInterface(conn, key_prefix=__, use_signer=False, permanent=True)
 34 
 35 class RedisSessionInterface(SessionInterface):
 36     serializer = pickle
 37     session_class = RedisSession
 38 
 39     def __init__(self, redis, key_prefix, use_signer=False, permanent=True):
 40         if redis is None:
 41             from redis import Redis
 42             redis = Redis()
 43         self.redis = redis
 44         self.key_prefix = key_prefix
 45         self.use_signer = use_signer
 46         self.permanent = permanent
 47 
 48     def open_session(self, app, request):
 49         sid = request.cookies.get(app.session_cookie_name)
 50         if not sid:
 51             sid = self._generate_sid()
 52             return self.session_class(sid=sid, permanent=self.permanent)
 53         if self.use_signer:
 54             signer = self._get_signer(app)
 55             if signer is None:
 56                 return None
 57             try:
 58                 sid_as_bytes = signer.unsign(sid)
 59                 sid = sid_as_bytes.decode()
 60             except BadSignature:
 61                 sid = self._generate_sid()
 62                 return self.session_class(sid=sid, permanent=self.permanent)
 63 
 64         if not PY2 and not isinstance(sid, text_type):
 65             sid = sid.decode(utf-8, strict)
 66         val = self.redis.get(self.key_prefix + sid)
 67         if val is not None:
 68             try:
 69                 data = self.serializer.loads(val)
 70                 return self.session_class(data, sid=sid)
 71             except:
 72                 return self.session_class(sid=sid, permanent=self.permanent)
 73         return self.session_class(sid=sid, permanent=self.permanent)
 74 
 75     def save_session(self, app, session, response):
 76         domain = self.get_cookie_domain(app)
 77         path = self.get_cookie_path(app)
 78         if not session:
 79             if session.modified:
 80                 self.redis.delete(self.key_prefix + session.sid)
 81                 response.delete_cookie(app.session_cookie_name,
 82                                        domain=domain, path=path)
 83             return
 84 
 85         # Modification case.  There are upsides and downsides to
 86         # emitting a set-cookie header each request.  The behavior
 87         # is controlled by the :meth:`should_set_cookie` method
 88         # which performs a quick check to figure out if the cookie
 89         # should be set or not.  This is controlled by the
 90         # SESSION_REFRESH_EACH_REQUEST config flag as well as
 91         # the permanent flag on the session itself.
 92         # if not self.should_set_cookie(app, session):
 93         #    return
 94 
 95         httponly = self.get_cookie_httponly(app)
 96         secure = self.get_cookie_secure(app)
 97         expires = self.get_expiration_time(app, session)
 98         val = self.serializer.dumps(dict(session))
 99         self.redis.setex(name=self.key_prefix + session.sid, value=val,
100                          time=total_seconds(app.permanent_session_lifetime))
101         if self.use_signer:
102             session_id = self._get_signer(app).sign(want_bytes(session.sid))
103         else:
104             session_id = session.sid
105         response.set_cookie(app.session_cookie_name, session_id,
106                             expires=expires, httponly=httponly,
107                             domain=domain, path=path, secure=secure)
View Code

 

 

 

以上是关于Flask中session源码执行过程的主要内容,如果未能解决你的问题,请参考以下文章

Flask框架 —— session源码分析

Flask - Session

Flask框架cbv的写法请求与响应请求扩展session源码分析闪现

flask-day2——cbv源码分析模版语法请求与响应session及源码分析闪现请求扩展

flask--session源码解析

flask Flask-Login 插件及继承 UserMixin 类login_user 源码分析session源码分析