flask_session_源码剖析
开始文件(部分):
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 | from flask import Flask,request,session app = Flask(__name__) app.secret_key = 'sdfsdfsd' from flask.sessions import SessionInterface,SessionMixin import uuid import json from flask.sessions import SessionInterface from flask.sessions import SessionMixin from itsdangerous import Signer, BadSignature, want_bytes class MySession( dict , SessionMixin): def __init__( self , initial = None , sid = None ): self .sid = sid self .initial = initial super (MySession, self ).__init__(initial or ()) def __setitem__( self , key, value): super (MySession, self ).__setitem__(key, value) def __getitem__( self , item): return super (MySession, self ).__getitem__(item) def __delitem__( self , key): super (MySession, self ).__delitem__(key) class MySessionInterface(SessionInterface): session_class = MySession container = { # 'asdfasdfasdfas':{'k1':'v1','k2':'v2'} # 'asdfasdfasdfas':"{'k1':'v1','k2':'v2'}" } def __init__( self ): pass # import redis # self.redis = redis.Redis() def _generate_sid( self ): return str (uuid.uuid4()) def _get_signer( self , app): if not app.secret_key: return None return Signer(app.secret_key, salt = 'flask-session' , key_derivation = 'hmac' ) def open_session( self , app, request): """ 程序刚启动时执行,需要返回一个session对象 """ sid = request.cookies.get(app.session_cookie_name) if not sid: # 生成随机字符串,并将随机字符串添加到 session对象中 sid = self ._generate_sid() return self .session_class(sid = sid) signer = self ._get_signer(app) try : sid_as_bytes = signer.unsign(sid) sid = sid_as_bytes.decode() except BadSignature: sid = self ._generate_sid() return self .session_class(sid = sid) # session保存在redis中 # val = self.redis.get(sid) # session保存在内存中 val = self .container.get(sid) if val is not None : try : data = json.loads(val) return self .session_class(data, sid = sid) except : return self .session_class(sid = sid) return self .session_class(sid = sid) def save_session( self , app, session, response): """ 程序结束前执行,可以保存session中所有的值 如: 保存到resit 写入到用户cookie """ domain = self .get_cookie_domain(app) path = self .get_cookie_path(app) httponly = self .get_cookie_httponly(app) secure = self .get_cookie_secure(app) expires = self .get_expiration_time(app, session) val = json.dumps( dict (session)) # session保存在redis中 # self.redis.setex(name=session.sid, value=val, time=app.permanent_session_lifetime) # session保存在内存中 self .container.setdefault(session.sid, val) session_id = self ._get_signer(app).sign(want_bytes(session.sid)) response.set_cookie(app.session_cookie_name, session_id, expires = expires, httponly = httponly, domain = domain, path = path, secure = secure) app.session_interface = MySessionInterface() # app.session_interface = Foo() # app.session_interface # app.make_null_session() @app .route( '/index' ) def index(): print ( '网站的所有session' ,MySessionInterface.container) print (session) session[ 'k1' ] = 'v1' session[ 'k2' ] = 'v2' del session[ 'k1' ] # 在内存中操作字典.... # session['k1'] = 'v1' # session['k2'] = 'v2' # del session['k1'] return "xx" if __name__ = = '__main__' : app.__call__ app.run() |

# 1. 执行Flask类的__call__ class RequestContext(object): def __init__(self,environ): self.environ = environ def push(self): # 3 # 请求相关数据,加到local中: stack.push... _request_ctx_stack.push(self) # 获取cookie中的随机字符串,检验是否有,没有就生成 # 根据随机字符串,获取服务端保存的session的 # { # 'xxxxxxx': {...} # 'xxxxxxx': {...} # } # 新用户: {} # 老用户:{user:'xxx'} self.session = self.app.open_session(self.request) if self.session is None: self.session = self.app.make_null_session() class Flask: def process_response(self, response): # 8 # 执行 after_request装饰器 for handler in funcs: response = handler(response) # 将内存中的session持久化到:数据库、.... if not self.session_interface.is_null_session(ctx.session): self.save_session(ctx.session, response) return response def finalize_request(self, rv, from_error_handler=False): # 7 response = self.make_response(rv) try: response = self.process_response(response) request_finished.send(self, response=response) except Exception: if not from_error_handler: raise self.logger.exception('Request finalizing failed with an ' 'error while handling an error') return response def full_dispatch_request(self): # 5 # 触发只执行一次的装饰器函数,@before_first_request self.try_trigger_before_first_request_functions() try: # 触发Flask的信号,没用: pip3 install blinker request_started.send(self) # 执行特殊装饰器:before_request # 如果没有返回值,rv=None;有返回值 “嘻嘻嘻” rv = self.preprocess_request() if rv is None: # 触发执行视图函数 rv = self.dispatch_request() except Exception as e: rv = self.handle_user_exception(e) # 6 对返回值进行封装 return self.finalize_request(rv) def wsgi_app(self, environ, start_response): # 处理request,将请求添加到local中 ctx = self.request_context(environ) # 2.处理request和session ctx.push() error = None try: try: # 4 执行视图函数 response = self.full_dispatch_request() except Exception as e: error = e response = self.handle_exception(e) except: error = sys.exc_info()[1] raise return response(environ, start_response) finally: if self.should_ignore_error(error): error = None # 9 ctx.auto_pop(error) def __call__(self, environ, start_response): """Shortcut for :attr:`wsgi_app`.""" # 1.xxx return self.wsgi_app(environ, start_response)
本文来自博客园,作者:一石数字欠我15w!!!,转载请注明原文链接:https://www.cnblogs.com/52-qq/p/8244636.html
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】凌霞软件回馈社区,博客园 & 1Panel & Halo 联合会员上线
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】博客园社区专享云产品让利特惠,阿里云新客6.5折上折
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· 一个奇形怪状的面试题:Bean中的CHM要不要加volatile?
· [.NET]调用本地 Deepseek 模型
· 一个费力不讨好的项目,让我损失了近一半的绩效!
· .NET Core 托管堆内存泄露/CPU异常的常见思路
· PostgreSQL 和 SQL Server 在统计信息维护中的关键差异
· DeepSeek “源神”启动!「GitHub 热点速览」
· 我与微信审核的“相爱相杀”看个人小程序副业
· 微软正式发布.NET 10 Preview 1:开启下一代开发框架新篇章
· 如何使用 Uni-app 实现视频聊天(源码,支持安卓、iOS)
· C# 集成 DeepSeek 模型实现 AI 私有化(本地部署与 API 调用教程)