flask基础之session原理详解(十) (2)

flask默认通过SecureCookieSessionInterface对象管理session,其重写了SessionInterface对象的open_session方法和save_session方法,将用户的数据加密后存储在cookie中。

自定义session存储

通过分析flask的session实现机制,一般认为将session信息放在cookie中不够保险,那么我们可以实现自己的session机制,思路是创建一个类继承SessionInterface,然后重写open_session方法和save_session方法,再使用我们的类替换app的session_interface属性即可。

比如我要将session信息保存在一个session.json中。

第一步:设置必要的配置参数 # 配置session存放的路径 MY_SESSION_PATH = '\session.json' 'SESSION_TYPE' = 'file' # 配置默认的seesion的配置参数 SECRET_KEY = '123' SESSION_USE_SIGNER = True # session的有效期,单位:秒 PERMANENT_SESSION_LIFETIME = 7200 第二步:创建自己的SessionInterface的子类 from flask.sessions import * try: import cPickle as pickle except ImportError: import pickle import json from uuid import uuid4 import time # 我们需要自定义一个Session对象用来存储用户的信息,它使用一个唯一的id标识,模仿SecureCookieSession的实现方法 class SecureFileSession(CallbackDict, SessionMixin): def __init__(self, initial=None, sid=None, permanent=None): def on_update(self): self.modified = True CallbackDict.__init__(self, initial, on_update) self.sid = sid # session的标识 if permanent: self.permanent = permanent # 失效时间 self.modified = False # 我们使用uuid作为签名,省略校验过程 class NewSessionInterface(SessionInterface): def _generate_sid(self): return str(uuid4()) class JsonFileSessionInterface(NewSessionInterface): # 用来序列化的包 serializer = pickle session_class = SecureFileSession def __init__(self, app=None): self.app = app if app is not None: self.init_app(app) def init_app(self, app): """ 替换app的session_interface属性 :param app: :return: """ app.session_interface = self._get_interface(app) def _get_interface(self, app): """ 加载配置参数返回本身,必须配置'SESSION_TYPE'和'MY_SESSION_PATH'参数,否则使用默认的session :param app: :return: """ config = app.config.copy() if config['SESSION_TYPE'] == 'file': if not config['MY_SESSION_PATH']: return SecureCookieSessionInterface() self.path = app.static_folder + config['MY_SESSION_PATH'] # session文件路径 self.permanent = total_seconds(app.permanent_session_lifetime) # 失效时间 return self return SecureCookieSessionInterface() def open_session(self, app, request): """ 从文件中获取session数据 :param app: :param request: :return: """ # 获取session签名 sid = request.cookies.get(app.session_cookie_name) permanent = int(time.time()) + self.permanent # 如果没有说明是第一次访问,返回空session对象 if not sid: # 获取一个uuid sid = self._generate_sid() return self.session_class(sid=sid, permanent=permanent) with open(self.path, 'r', encoding='utf-8') as f: v = f.read() # 如果session为空,返回空session对象 if not v: return self.session_class(sid=sid, permanent=permanent) try: val = json.loads(v) except ValueError as e: print('配置参数错误:{}'.format(e)) return self.session_class(sid=sid, permanent=permanent) else: self.val = val # 通过sid获取信息 data = val.get(sid) if not data: return self.session_class(sid=sid, permanent=permanent) # 判断以前的信息是否超时 if permanent - int(data['permanent']) > self.permanent: return self.session_class(sid=sid, permanent=permanent) return self.session_class(data, sid=sid) def save_session(self, app, session, response): """ 保存session信息 :param app: :param session: :param response: :return: """ # 前面借鉴flask默认的实现方式 domain = self.get_cookie_domain(app) path = self.get_cookie_path(app) if not session: if session.modified: response.delete_cookie(app.session_cookie_name, domain=domain, path=path) return if not self.should_set_cookie(app, session): return httponly = self.get_cookie_httponly(app) secure = self.get_cookie_secure(app) expires = self.get_expiration_time(app, session) # 将session信息保存在文件中 session.update({'permanent': int(time.time()) + self.permanent}) if hasattr(self, 'val') and isinstance(self.val, dict): self.val.update({session.sid: dict(session)}) else: self.val = {session.sid: dict(session)} with open(self.path, 'w', encoding='utf-8') as f: result = json.dumps(self.val) f.write(result) response.set_cookie(app.session_cookie_name, session.sid, expires=expires, httponly=httponly, domain=domain, path=path, secure=secure) 第三步:初始化替换app的session_interface app = Flask(__name__,template_folder='static/html') app.config.update({ 'SECRET_KEY':'123', 'SESSION_USE_SIGNER':True, 'SESSION_TYPE':'file', 'MY_SESSION_PATH':'\session.json'}) from session_file import JsonFileSessionInterface se = JsonFileSessionInterface(app=app) if __name__ == '__main__': app.run(host='127.0.0.1', port=80, debug=True) 小结

内容版权声明:除非注明,否则皆为本站原创文章。

转载注明出处:https://www.heiqu.com/wpfzpw.html