koa-session 获取当前会话的 sessionid
使用 koa-session
时,获取 sessionid。
tl;dr
先说结论,如果在使用 koa-session
时需要获取当前新建 session
的 sessionid
时,可以通过手动调用 koa-session
的 save
方法立即保存当前的 session 更改,即 await ctx.session.manuallyCommit();
或 await ctx.session.save();
(强制保存),调用后,我们可以在 ctx.response.header
的 set-cookie
属性中拿到当前的 sessionid
。
接下来说下场景和原因。
场景
项目技术背景如下,其中单点的逻辑这里简化描述,我们目前使用的方案是 CAS,下文我们也会用 CAS 表述单点服务。
使用了
koas-session
管理 session
使用 redis 存储 session(这个可以在 session 方法的 opitons 属性中配置)
接入了 CAS,登录成功后,我会把 CAS 下发的 ticket 和当前 session 的 sessionid,存入 redis(退出登录时会使用到)
在服务里给 CAS 预留一个登出入口,CAS 登出时会请求这个接口,我们可以拿到 CAS 带来的 ticket 参数,通过 ticket,我们可以从 redis 里拿到对应的 sessionid,再通过 sessionid 销毁对应的 session
注:用户在接入 CAS 的项目中登出时,CAS 会对所有接入的端发送登出的请求,各个端系统在预留的登出接口里配置 session 销毁逻辑
这个方案没有问题,唯一的问题在于实现时发现,koa-session
并没有暴露当前 sessionid
的方法,如果拿不到 sessionid
,整个流程都会被卡主,获取方法前面已经提过了,下面我们聊聊为什么。
原因
看过 koa-session
源码的同学应该知道,当使用外部存储时(mongo、redis 等)时,以 redis 为例,这个中间件会将 session
数据存在 redis 里,将 sessionid
写入客户端的 cookie
,当客户端再次请求时,通过读取 cookie
,再从 redis 中拿出 session。
1 | // 保存到外部存储 |
当看到 this.ctx.cookies.set(key, externalKey, opts);
这行代码时,意识到可以通过拿 set-cookie
来获取,但是,在配置 session 后,打印 response.header
时却没看到任何 set-cookie
的信息,再看源码,上面保存的方法被放置到了最后触发
1 | module.exports = function(opts, app) { |
这样就太被动了,不过还好暴露除了 save
和 manuallyCommit
两种方式触发保存,区别是 save
是冒着 session 被污染的风险强制更新,保存之后,再次打印,令人满意的 set-cookie
如约出现。
多一种方案
获取 koa-session
默认生成的 sessionid
,只是一种方案,我们还可以生成自定义 sessionid
,配置到 option
中的 externalKey
属性,可以达到制定 sessionid
的目的。
作者: leeon
来源: https://leeon.im
链接: https://leeon.im/koa-session-get-session-id/
本文采用知识共享署名-非商业性使用 4.0 国际许可协议进行许可