Flask中session源码执行过程

1.面向对象补充知识metaclass

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

a.普通方式

1 class Foo(object):
2
3     def func(self):
4         print ‘hello wupeiqi‘

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

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

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()

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         )

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()

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)

 

原文地址:https://www.cnblogs.com/chenjunkan/p/10007862.html

时间: 2024-11-12 11:35:46

Flask中session源码执行过程的相关文章

Flask框架 —— session源码分析

目录 session源码分析 1.请求来了,执行__call__方法 2.__call__方法 3.调用__call__方法 3.1.ctx = self.request_context(environ) --- 得到空的session 3.2.ctx.push() --- 调用open_session方法 3.3.self.full_dispatch_request() --- 路由分发,执行函数,写入session session源码分析 1.请求来了,执行__call__方法 # 请求来了

Linux中centos中httpd源码安装过程详解

在Linux中软件安装有两大类,一类是软件包安装,一类是源代码安装.软件包安装就是指将编译好的二进制封装成rpm包,可以直接使用rpm工具和yum工具安装.源代码安装是指没有编译成二进制,需要通过手动编译的.使用源代码安装的原因有两个,一个就是想使用最新版的软件,另一类就是想自定义其功能的. 在httpd的源码安装过程中需要用到:APR.APR-UTIL. PCRE.httpd源码安装过程:1.展开压缩文件,把压缩文件解压缩到/usr/local/src.2.在解压文件目录使用 ./config

mysql-5.5.28源码安装过程中错误总结

介绍一下关于mysql-5.5.28源码安装过程中几大错误总结,希望此文章对各位同学有所帮助.系统centOS 6.3 mini (没有任何编译环境)预编译环境首先装了众所周知的 cmake(yum install cmake -y) 复制代码 代码如下: ../bootstrap Error when bootstrapping CMake: Cannot find appropriate C compiler on this system. Please specify one using

Flask中session实现原理

前言 flask_session是flask框架实现session功能的一个插件,用来替代flask自带的session实现机制,flask默认的session信息保存在cookie中,不够安全和灵活. flask的session机制 session是用来干什么的呢?由于http协议是一个无状态的协议,也就是说同一个用户第一次请求和第二次请求是完全没有关系的,但是现在的网站基本上有登录使用的功能,这就要求必须实现有状态,而session机制实现的就是这个功能. 实现的原理: 用户第一次请求后,将

flask 请求上下文源码(转)

本篇阅读目录 一.flask请求上下文源码解读 二.http聊天室(单聊/群聊)- 基于gevent-websocket 回到顶部 转:https://www.cnblogs.com/li-li/p/10252058.html#main 一.flask请求上下文源码解读 通过上篇源码分析,我们知道了有请求发来的时候就执行了app(Flask的实例化对象)的__call__方法,而__call__方法返回了app的wsgi_app(environ, start_response)方法的执行结果,而

Flume-NG(1.5版本)中SpillableMemoryChannel源码级分析

SpillableMemoryChannel是1.5版本新增的一个channel.这个channel优先将evnet放在内存中,一旦内存达到设定的容量就使用file channel写入磁盘.然后读的时候会按照顺序读取:会通过一个DrainOrderQueue来保证不管是内存中的还是溢出(本文的“溢出”指的是内存channel已满,需要使用file channel存储数据)文件中的顺序.这个Channel是memory channel和file channel的一个折中,虽然在内存中的数据仍然可能

Mariadb源码编译过程

从微博上看到有人提及Mariadb,搜索了一下,找到地址https://mariadb.org/,这是mysql的一个分支,由原作者维护,意在与oracle分庭抗礼,避免oracle将来毕源. 目前版本Mariadb 10.0.10,我下载了一个,准备编译一个64位版本,下载地址: https://downloads.mariadb.org/mariadb/10.0.10/ 下载后用cmake编译一下试试,进入cmake图形界面,编译器选择vs12.0 win64 Warning: Bison

Django——Session源码分析

首先我们导入django.contrib.sessions.middleware这个中间件,查看里面的Session源码 from django.contrib.sessions.middleware import SessionMiddleware 我们可以看到一个类,可以把他分为3部分: class SessionMiddleware(MiddlewareMixin): def __init__(self, get_response=None): ... def process_reques

cocos2d-x 3.1.1源码阅读过程的注释

cocos2d-x 3.1.1源码阅读过程的注释 印象笔记链接:http://app.yinxiang.com/l/AAU8F1mKiN9BIqFopReAU3ZbTcgGOULycQo/ Ref 每个类的基类是Ref   也就是2.0的CCObject 调用继承下来的下面的那个函数 class CC_DLL Ref { public: /** 引用计数+1 */ void retain(); { CCASSERT(_referenceCount > 0, "reference count