springboot通过sessionid获取session_koa-session 获取当前会话的 sessionid

f46d6746cc090470af5544a75272097b.png
原文:koa-session 获取当前会话的 sessionid


使用 koa-session 时,获取 sessionid。

tl;dr

先说结论,如果在使用 koa-session 时需要获取当前新建 sessionsessionid 时,可以通过手动调用 koa-sessionsave 方法立即保存当前的 session 更改,即 await ctx.session.manuallyCommit();await ctx.session.save();(强制保存),调用后,我们可以在 ctx.response.headerset-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。

// 保存到外部存储
if (externalKey) {
  debug('save %j to external key %s', json, externalKey);
  if (typeof maxAge === 'number') {
    maxAge += 10000;
  }
  await this.store.set(externalKey, json, maxAge, {
    changed,
    rolling: opts.rolling,
  });
  if (opts.externalKey) {
    opts.externalKey.set(this.ctx, externalKey);
  } else {
    this.ctx.cookies.set(key, externalKey, opts);
  }
  return;
}

当看到 this.ctx.cookies.set(key, externalKey, opts); 这行代码时,意识到可以通过拿 set-cookie 来获取,但是,在配置 session 后,打印 response.header 时却没看到任何 set-cookie 的信息,再看源码,上面保存的方法被放置到了最后触发

module.exports = function(opts, app) {
  if (opts && typeof opts.use === 'function') {
    [ app, opts ] = [ opts, app ];
  }
  if (!app || typeof app.use !== 'function') {
    throw new TypeError('app instance required: `session(opts, app)`');
  }
  opts = formatOpts(opts);
  extendContext(app.context, opts);
  return async function session(ctx, next) {
    const sess = ctx[CONTEXT_SESSION];
    if (sess.store) await sess.initFromExternal();
    try {
      await next();
    } catch (err) {
      throw err;
    } finally {
      if (opts.autoCommit) {
        // commit 方法中执行上文的保存操作
        await sess.commit();
      }
    }
  };
};

这样就太被动了,不过还好暴露除了 savemanuallyCommit 两种方式触发保存,区别是 save 是冒着 session 被污染的风险强制更新,保存之后,再次打印,令人满意的 set-cookie 如约出现。

多一种方案

获取 koa-session 默认生成的 sessionid,只是一种方案,我们还可以生成自定义 sessionid,配置到 option 中的 externalKey 属性,可以达到制定 sessionid 的目的

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值