flask_session_源码剖析
开始文件(部分):
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