news 2026/9/5 10:25:57

Flask入门教程(二十七):Session Interface API——自定义Session存储后端

作者头像

张小明

前端开发工程师

1.2k 24
文章封面图
Flask入门教程(二十七):Session Interface API——自定义Session存储后端

1. SessionInterface抽象基类

SessionInterface定义了Session存储后端需要实现的核心接口。

属性/方法说明
null_session_class当Session不可用时使用的类,默认为NullSession
pickle_basedSession是否基于pickle序列化,默认为False
open_session(app, request)从请求中读取Session数据,返回SessionMixin实例或None
save_session(app, session, response)将Session数据保存到响应中
make_null_session(app)创建空Session,open_session返回None时自动调用
is_null_session(obj)判断是否为NullSession实例

2. Cookie选项方法

以下方法用于获取Session Cookie的各项属性,可被子类重写:

方法说明
get_cookie_name(app)获取Cookie名称,默认读取SESSION_COOKIE_NAME配置
get_cookie_domain(app)获取Cookie Domain,默认读取SESSION_COOKIE_DOMAIN
get_cookie_path(app)获取Cookie Path,默认读取SESSION_COOKIE_PATHAPPLICATION_ROOT
get_cookie_httponly(app)获取HttpOnly标志,默认读取SESSION_COOKIE_HTTPONLY
get_cookie_secure(app)获取Secure标志,默认读取SESSION_COOKIE_SECURE
get_cookie_samesite(app)获取SameSite值,默认读取SESSION_COOKIE_SAMESITE
get_cookie_partitioned(app)获取Partitioned标志,默认读取SESSION_COOKIE_PARTITIONED(v3.1+)
get_expiration_time(app, session)获取Session过期时间,永久Session返回now + lifetime
should_set_cookie(app, session)判断是否需要设置Cookie

3. 内置实现

说明
SecureCookieSessionInterface默认实现。使用itsdangerous签名Cookie存储Session数据
SecureCookieSession基于CallbackDict的Session类,检测顶层键的修改自动设置modified=True
NullSession未设置SECRET_KEY时使用的占位Session,读取正常但修改时报错
SessionMixinSession类的Mixin,提供permanentnewmodifiedaccessed属性

4. 替换默认Session实现

自定义内存Session(示例)

from flask import Flask from flask.sessions import SessionInterface, SessionMixin from uuid import uuid4 # 自定义Session类(存储用户数据) class MySession(dict, SessionMixin): def __init__(self, session_id=None, data=None): super().__init__() self.session_id = session_id or str(uuid4()) if data: self.update(data) self.permanent = False # 自定义Session接口(内存存储) class MySessionInterface(SessionInterface): # 模拟数据库存储(实际生产环境应使用Redis等) _store = {} def open_session(self, app, request): # 从Cookie中获取session_id session_id = request.cookies.get("my_session_id") if session_id and session_id in self._store: data = self._store[session_id] return MySession(session_id, data) # 创建新Session return MySession() def save_session(self, app, session, response): if not session: return # 如果Session为空,删除Cookie if not session: response.delete_cookie("my_session_id") return # 保存数据到存储 self._store[session.session_id] = dict(session) # 设置Cookie response.set_cookie( "my_session_id", session.session_id, max_age=app.permanent_session_lifetime.total_seconds() if session.permanent else None, httponly=True, secure=app.config.get("SESSION_COOKIE_SECURE", False), samesite=app.config.get("SESSION_COOKIE_SAMESITE", "Lax") ) # 应用配置 app = Flask(__name__) app.secret_key = "dev-secret" app.session_interface = MySessionInterface() @app.route("/") def index(): session["count"] = session.get("count", 0) + 1 return f"访问次数: {session['count']}"

5. 使用Redis存储Session(生产级示例)

import redis import pickle from flask import Flask from flask.sessions import SessionInterface, SessionMixin from uuid import uuid4 from datetime import timedelta class RedisSession(dict, SessionMixin): """Redis存储的Session类""" def __init__(self, session_id=None, data=None, expiry=None): super().__init__() self.session_id = session_id or str(uuid4()) self.permanent = False self.expiry = expiry if data: self.update(data) class RedisSessionInterface(SessionInterface): """使用Redis存储Session""" def __init__(self, redis_client, key_prefix="session:"): self.redis = redis_client self.key_prefix = key_prefix def _get_key(self, session_id): return f"{self.key_prefix}{session_id}" def open_session(self, app, request): session_id = request.cookies.get(app.config.get("SESSION_COOKIE_NAME", "session")) if session_id: key = self._get_key(session_id) data = self.redis.get(key) if data: try: data_dict = pickle.loads(data) return RedisSession(session_id, data_dict) except: pass return RedisSession() def save_session(self, app, session, response): if not session: return key = self._get_key(session.session_id) # 如果Session为空,删除Redis数据并清除Cookie if not session: self.redis.delete(key) response.delete_cookie(app.config["SESSION_COOKIE_NAME"]) return # 计算过期时间 if session.permanent: lifetime = app.config.get("PERMANENT_SESSION_LIFETIME", timedelta(days=31)) else: lifetime = timedelta(days=1) # 序列化并保存到Redis self.redis.setex(key, int(lifetime.total_seconds()), pickle.dumps(dict(session))) # 设置Cookie response.set_cookie( app.config["SESSION_COOKIE_NAME"], session.session_id, max_age=int(lifetime.total_seconds()) if session.permanent else None, httponly=app.config.get("SESSION_COOKIE_HTTPONLY", True), secure=app.config.get("SESSION_COOKIE_SECURE", False), samesite=app.config.get("SESSION_COOKIE_SAMESITE", "Lax") ) # 使用 import redis r = redis.Redis(host="localhost", port=6379, db=0) app = Flask(__name__) app.secret_key = "dev-secret" app.session_interface = RedisSessionInterface(r) @app.route("/") def index(): session["views"] = session.get("views", 0) + 1 return f"访问次数: {session['views']}"

6. 什么时候需要自定义SessionInterface

场景说明
多服务器/负载均衡默认签名Cookie在单服务器可用,多服务器间需共享Session存储
Session数据量较大Cookie有4KB限制,外部存储无此限制
需要服务端Session控制如强制下线、Session黑名单等
与现有系统集成需对接已有的Session存储体系
审计和安全要求需要完整的服务端Session日志

7. 不同Session方案对比

存储方式优点缺点适用场景
签名Cookie(默认)无状态、无需服务端存储、部署简单4KB限制、数据可见、无法主动失效单机应用、轻量Session
Redis高性能、支持过期、多服务器共享需要额外服务、网络延迟分布式应用、高并发
数据库持久化、支持复杂查询性能较低对持久性要求高的场景
Memcached高性能不支持持久化缓存型Session

8. SessionInterface API速查表

类别方法说明
核心open_session(app, request)从请求加载Session数据
核心save_session(app, session, response)保存Session到响应
Cookieget_cookie_name(app)Cookie名称
Cookieget_cookie_secure(app)Secure标志
Cookieget_cookie_httponly(app)HttpOnly标志
Cookieget_cookie_samesite(app)SameSite值
Cookieget_expiration_time(app, session)过期时间
工具should_set_cookie(app, session)是否设置Cookie
工具make_null_session(app)创建空Session

小结

本章全面讲解了Flask Session Interface的完整API。SessionInterface是Session存储的底层抽象,通过open_session(app, request)从请求加载Session数据,通过save_session(app, session, response)将Session保存到响应;Cookie相关方法(get_cookie_nameget_cookie_secureget_cookie_httponlyget_cookie_samesite等)可被子类重写以自定义Cookie属性;Flask默认使用SecureCookieSessionInterface(签名Cookie存储);通过替换app.session_interface可切换为Redis、数据库等外部存储,解决多服务器共享、数据量限制等问题。自定义SessionInterface是实现分布式Session管理的核心手段。

版权声明: 本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若内容造成侵权/违法违规/事实不符,请联系邮箱:809451989@qq.com进行投诉反馈,一经查实,立即删除!
网站建设 2026/9/5 10:21:57

小天鹅小乌梅5.0轻享版K20滚筒洗衣机10KG深度评测与选购指南

/* MD / 富文本中的 .toc(含博客园搬家等嵌套结构);.toc-box 在侧栏,不受影响 */#content_views .toc,/* 编辑器常在目录前后插入空 p(:empty 仍占 20px),一并去掉避免顶空隙 */#content_views.markdown_views > p:empty:has(+ .toc),#content_views.markdown_views …

作者头像 李华
网站建设 2026/9/5 10:21:52

Unity生存建造游戏开发实战:从零构建海上木筏求生Demo

/* MD / 富文本中的 .toc(含博客园搬家等嵌套结构);.toc-box 在侧栏,不受影响 */#content_views .toc,/* 编辑器常在目录前后插入空 p(:empty 仍占 20px),一并去掉避免顶空隙 */#content_views.markdown_views > p:empty:has(+ .toc),#content_views.markdown_views …

作者头像 李华
网站建设 2026/9/5 10:21:29

Magnitude:免费、私密、离线运行本地模型,多优势助力开发者!

【Magnitude:免费私密离线运行本地模型】Magnitude 是一款开源推理服务器,它能为硬件匹配最适合的本地模型,并与现有的代理集成。它会分析机器性能,推荐适配的模型,然后完成下载、调优和运行等操作。Magnitude 可与 Pi…

作者头像 李华
网站建设 2026/9/5 10:21:22

Python面向对象:__call__让实例对象可调用的方法

Python面向对象:__call__让实例对象可调用的方法一、开篇:把对象变成函数 在Python中,函数是可调用对象——你给它加括号传参就能执行。但你知道吗?你可以让自己的类的实例也变成可调用的——就像函数一样。 ⌨️ 这就是__call__&…

作者头像 李华
网站建设 2026/9/5 10:21:10

本地AI Agent从零搭建:Ollama+Dify打造私有化数字员工

/* MD / 富文本中的 .toc(含博客园搬家等嵌套结构);.toc-box 在侧栏,不受影响 */#content_views .toc,/* 编辑器常在目录前后插入空 p(:empty 仍占 20px),一并去掉避免顶空隙 */#content_views.markdown_views > p:empty:has(+ .toc),#content_views.markdown_views …

作者头像 李华