news 2026/9/28 6:25:10

Midway Session 组件完全指南:从 Cookie Session 到自定义 Session Store 的落地实践

作者头像

张小明

前端开发工程师

1.2k 24
文章封面图
Midway Session 组件完全指南:从 Cookie Session 到自定义 Session Store 的落地实践
  • 后端
  • 微服务
  • 云原生

【免费下载链接】midway

🍔 A Node.js Serverless Framework for front-end/full-stack developers. Build the application for next decade. Works on AWS, Alibaba Cloud, Tencent Cloud and traditional VM/Container. Super easy integrate with React and Vue. 🌈

项目地址:https://gitcode.com/gh_mirrors/mi/midway
点击查看免费下载

本文以@midwayjs/session组件(位于 packages/session)为主体,系统讲解在 Midway(Koa / FaaS)应用中启用与配置 Session 的完整路径:默认配置、可继承的 koa-session 全量参数、以及通过实现抽象类SessionStore接入自定义存储的实战方案。读完本文,你将能够开箱即用地完成用户会话读写、理解底层ctx.session的存取与自动提交机制,并在 Redis、MySQL 等外部存储中落地自己的 Session Store。

组件定位与适用场景

@midwayjs/session是 Midway 官方为@midwayjs/koa与@midwayjs/faas提供的 Session 组件。它的核心职责是:

  • 将 Session 能力挂载到请求上下文,提供ctx.session/ctx.sessionOptions访问入口(见 middleware/session.ts);
  • 默认使用Cookie 直存模式(Session 数据经 Base64 + JSON 编码写入 Cookie,体积小、免存储依赖);
  • 支持通过自定义SessionStore切换为外部存储模式(数据存放在 Redis、数据库等,Cookie 中只保存一个会话 ID 外键);
  • 自动监听会话缺失(missed)、过期(expired)、非法(invalid)等事件并输出日志。

组件内部依赖@midwayjs/cookies完成 Cookie 的读写与签名,相关声明可见 package.json。

安装与接入

安装命令:

$ npm i @midwayjs/session --save

接入方式分两种框架:

  • @midwayjs/koa默认已启用该组件,无需额外配置即可使用;
  • @midwayjs/faas需要手动启用,在src/configuration.ts中将其加入imports:
// src/configuration.ts import { join } from 'path'; import * as faas from '@midwayjs/faas'; import * as session from '@midwayjs/session'; @Configuration({ imports: [ faas, session, ], // ... }) export class ContainerLifeCycle implements ILifeCycle {}

组件通过 configuration.ts 中的SessionConfiguration完成装配:在onReady阶段读取session配置,若enable为真,则向所有 koa/faas 应用注册SessionMiddleware,并挂载session:missed、session:expired、session:invalid三个事件的日志监听。

默认配置与完整参数说明

在config.*.ts中通过session配置项进行定制。组件的默认配置位于 config/config.default.ts,实际默认值如下:

export const session = { enable: true, maxAge: 24 * 3600 * 1000, // ms,即 1 天 key: 'MW_SESS', httpOnly: true, // sameSite: null, logValue: true, };

参数说明:

参数默认值说明
enabletrue是否启用 Session 中间件,关闭后ctx.session不再注入
maxAge24 * 3600 * 1000(毫秒)Session 有效期。注意代码注释中的 Cookie key 默认名与默认配置存在历史差异,实际生效值为MW_SESS(测试 index.test.ts 中同样以MW_SESS断言)
key'MW_SESS'存放会话的 Cookie 名
httpOnlytrue禁止客户端 JavaScript 读取 Cookie;若设置为false,中间件会在启动时输出安全警告
sameSitenull(不设置)默认删除空值;需要时可按koa-session语义显式配置lax/strict/none
logValuetrue会话过期/非法时,是否在session:expired/session:invalid日志中打印会话内容

可继承的 koa-session 全量选项

README 明确指出“you can use all config from koa-session”,这些选项在 interface.ts 的SessionOptions中有完整类型定义,并在 middleware/session.ts 的formatOpts中被逐一校验、赋默认值。常用项如下:

  • maxAge:除了毫秒数值,还可设置为'session',表示会话级 Cookie(浏览器/会话关闭即失效);底层在save时会写入_session: true标记并清空maxAge,同时跳过_expire字段(见 lib/context.ts);
  • rolling(默认false):每次响应都强制重写会话 Cookie,重置过期倒计时,适合“持续活跃即续期”的场景;
  • renew(默认false):会话在剩余寿命不足maxAge / 2时自动续期,用于“长期保持登录”;
  • genid:外部存储模式下生成会话 ID 的函数,默认Utils.randomUUID;若配置了prefix则生成prefix + UUID;
  • prefix:外部会话 ID 的统一前缀(genid存在时忽略);
  • externalKey:自定义“外部键”的get/set方法,默认从opts.key对应的 Cookie 中读取;
  • ContextStore:需要从ctx获取依赖的存储类,每个请求执行一次new ContextStore(ctx),需实现get/set/destroy三个实例方法;
  • valid(ctx, session):读取到会话值后、使用前的校验钩子,返回false即触发session:invalid事件并重建会话;
  • beforeSave(ctx, session):会话落盘前的钩子,可在此做数据加工;
  • autoCommit(默认true):请求结束后是否自动提交会话;设为false时需手动调用ctx.session.manuallyCommit();
  • overwrite/signed:Cookie 覆盖写入与签名,默认均为true;
  • encode/decode:自定义 Cookie 内容的编解码函数,默认实现见 lib/util.ts(JSON.stringify后转 Base64,读取时反向解码)。

配置校验逻辑集中在 middleware/session.ts 的formatOpts:store必须提供get/set/destroy,externalKey必须提供get/set,ContextStore必须是具备上述三方法的类,否则启动时直接断言报错。

使用方式:Cookie Session 模式

在不配置任何 Store 的情况下,Session 数据直接存入MW_SESSCookie(Base64 编码的 JSON)。控制器中读写如下:

import { Controller, Get } from '@midwayjs/core'; @Controller('/') export class HomeController { @Get('/set') async set(ctx) { ctx.session.foo = 'bar'; // 写入会话 return ctx.session; } @Get('/get') async get(ctx) { return ctx.session; // 读取会话(未写数据时不产生 Set-Cookie) } @Get('/remove') async remove(ctx) { ctx.session = null; // 置空即删除会话(响应 204 并清除 Cookie) } }

ctx.session对象的能力由 lib/session.ts 中的Session类提供:

  • ctx.session.key = value写入、直接读取即取值;
  • ctx.session.maxAge = 100:动态修改有效期,修改后会强制落盘(_requireSave = true);
  • ctx.session.regenerate(callback?):重新生成会话(先删除旧会话,再生成新外部键);
  • ctx.session.save(callback?):无论会话是否有数据都强制保存;
  • ctx.session.manuallyCommit():配合autoCommit: false手动提交;
  • session.length/session.populated:判断会话是否已有数据;
  • session.externalKey:仅外部存储模式下存在,返回当前会话的存储键。

底层流程在 lib/context.ts 中:中间件首次访问ctx.session时按需initFromCookie()(解析、valid校验、失败则重建);响应阶段由中间件的finally块调用commit(),通过 lib/util.ts 的 CRC32 哈希对比判断会话是否变更,未变更且未开启rolling/renew时跳过写 Cookie;ctx.session = null则触发remove(),以 1970 年过期时间清除 Cookie。上述行为均有对应测试覆盖,见 test/index.test.ts。

自定义 Session Store:接入外部存储

当会话数据较大或需要跨进程共享(多实例部署、Serverless 场景)时,应切换到外部存储模式。

第一步:继承SessionStore抽象类

在 interface.ts 中定义了抽象类,需要实现三个方法:

import { SessionStore } from '@midwayjs/session'; @Provide() @Scope(ScopeEnum.Singleton) export class MemorySessionStore extends SessionStore { sessions = {}; async get(key) { return this.sessions[key]; } async set(key, value) { this.sessions[key] = value; } async destroy(key) { this.sessions[key] = undefined; } }

注意抽象类的方法签名(见 interface.ts):

export abstract class SessionStore { abstract get(key: string); abstract set(key: string, value: string, maxAge: number); abstract destroy(key); }
  • set的第三个参数maxAge用于让 Redis 等支持 TTL 的存储自动过期;底层在落盘时会额外+10000(10 秒)以保证存储先于 Cookie 过期(见 lib/context.ts 的save方法);
  • 存储中会写入_expire、_maxAge(或_session)内部字段,读取时由Session构造器还原maxAge;
  • 实现类需标记为@Provide()的单例,供容器注入。

第二步:通过SessionStoreManager注入到组件

SessionStoreManager(见 lib/store.ts)是单例管理器,提供setSessionStore/getSessionStore。中间件在resolve阶段会取出管理器中的 Store 并写入sessionConfig.store(见 middleware/session.ts)。接入方式:

import { MemorySessionStore } from './store'; import * as session from '@midwayjs/session'; @Configuration({ imports: [ koa, session, ], //... }) export class AutoConfiguration { @Inject() memoryStore: MemorySessionStore; @Inject() sessionStoreManager: session.SessionStoreManager; async onReady() { this.sessionStoreManager.setSessionStore(this.memoryStore); } }

切换到外部存储后,Cookie 中不再保存完整会话数据,而是只保存由genid生成的会话 ID(默认 UUID),会话数据以该 ID 为键写入 Store。仓库中的 memory-session 测试用例 就是这一模式的最小可运行示例。

会话事件与日志排查

ContextSession在会话读取异常时通过emit触发应用级事件(lib/context.ts),组件在 configuration.ts 中统一监听并输出 warn 日志:

  • session:missed:会话键在存储中不存在;
  • session:expired:_expire早于当前时间,判定过期;
  • session:invalid:valid钩子校验失败。

expired/invalid的日志内容是否打印由logValue配置控制,生产环境若担心敏感信息泄漏可设为false。

总结与选型建议

  • 单机、会话数据小:使用默认的 Cookie Session,零配置即可用,注意 Cookie 大小上限(约 4KB);
  • 多实例、会话共享、数据量大:实现SessionStore(如基于ioredis的 Redis Store),配合maxAge的 TTL 参数实现自动过期,并开启rolling或renew控制续期策略;
  • 安全基线:保持httpOnly: true,key使用不易猜测的名称,会话写 Cookie 依赖的签名密钥需妥善管理。

本文所涉源码均可从仓库对应路径继续深入阅读:默认配置、选项类型定义、中间件与参数校验、会话上下文管理、会话模型、Store 管理器 以及 功能测试。

  • 后端
  • 微服务
  • 云原生

【免费下载链接】midway

🍔 A Node.js Serverless Framework for front-end/full-stack developers. Build the application for next decade. Works on AWS, Alibaba Cloud, Tencent Cloud and traditional VM/Container. Super easy integrate with React and Vue. 🌈

项目地址:https://gitcode.com/gh_mirrors/mi/midway
点击查看免费下载
上一篇:如何永久保存微信聊天记录:WeChatMsg免费工具完整指南
下一篇:wechat-bot:10 分钟搭好一个微信机器人,多 AI 自动回复 + 群聊分析

创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考

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

ROS+PX4+Gazebo无人机仿真深度调优指南

1. 为什么“ROSPX4Gazebo”组合至今仍是无人机仿真不可绕过的铁三角?你刚在Ubuntu 22.04上敲完sudo apt install ros-humble-desktop,终端回显“Done”,心里一松——ROS装好了。可当你打开QGroundControl,加载PX4固件,…

作者头像 李华
网站建设 2026/9/28 6:24:04

NebulaGraph部署运维实战:从单机到集群的指令清单

NebulaGraph 这个分布式图数据库,我从 2.x 时代就开始在项目里用了。老实讲,图数据库的上手曲线并不低,尤其是第一次部署时,meta、storaged、graphd 三类服务的关系能把人绕晕。好在折腾过几轮之后,我手里的指令清单越…

作者头像 李华
网站建设 2026/9/28 6:23:30

国产AI编程工具深度评测:从Cursor替代到实战落地指南

开始正文用AI写代码这件事,这两年算是彻底出圈了。国外有个叫Cursor的编辑器,硬生生靠着AI能力,从VS Code、JetBrains这些老牌IDE嘴里抢走了大量用户,GitHub上很多开源项目都直接标注“本仓库由Cursor辅助开发”。身边不少同事从抵…

作者头像 李华
网站建设 2026/9/28 6:21:12

372张VOC+YOLO双格式数据训练目标检测模型实战

简介:面向药品识别与目标检测场景,一款999感冒灵检测数据集可为计算机视觉学习者、算法工程师提供可直接投入训练的标注数据。资源围绕单一目标类别“999ganmaoling”构建,共372张jpg原图,每张图片都同时包含VOC格式xml与YOLO格式…

作者头像 李华
网站建设 2026/9/28 6:20:28

C++静态分析工具横评:Clang-Tidy、Cppcheck、PVS-Studio与CodeQL实战对比

C静态分析工具这个题目,我是交过学费的。第一次把PVS-Studio接入公司CI的时候,编译通过、测试全绿,但静态分析报告一下打印出三千多条告警,全组对着那份输出沉默了好几分钟。从那以后我花了大量时间研究不同静态分析工具在真实项目…

作者头像 李华