Egg: 在程序中用了egg-redis、egg-session-redis插件,通过this.ctx.session设置了session之后,存在redis中是以set形式存储的,但是key是一个自动生成的编码。那么如何获取到存在redis中的session的key呢?求指教!!!

Created on 23 Jan 2018  ·  14Comments  ·  Source: eggjs/egg

  • Node Version:v8.9
  • Egg Version:2.0
  • Plugin Name:redis-session,redis-session-redis
  • Plugin Version:1.0,1.0
  • Platform:centos
  • Mini Showcase Repository:

Most helpful comment

this.ctx.session._sessCtx.externalKey

不知是不是各位想要的。。。

All 14 comments

为什么要获取?

@dead-horse 想要在缓存中存取,进行对单端登陆的验证!

不需要通过key获取,直接在request 中获取session就可以了呀,会话未结果可以直接从session拿

如果是基于 ip 做限制,将 ip 写到 session 中即可,自行做校验。如果一定要获取到 key,可以通过 opts. genid 参数来自行控制 session id 的生成方式。文档地址:https://github.com/koajs/session

@dead-horse 当使用CAS做单点登出的时候,是需要获取session id的。原因:

如果有A,B两个子系统。它们都处于登录状态,当B系统退出登录,A系统也需要自动退出,这样A系统之前存储在redis中的session就需要手动进行销毁。现在因为没有sessionId,无法销毁session,导致A系统刷新页面,仍然处于登录状态。

提到的配置opts.genid,我在config.default.js中:
config.session = { genid: () => return uuid;}

但存在的问题是,config.default.js中无法获取ctx,如何将该id传到middleware中进行使用呢?

我看了koa-session源码,不知道作者出于什么样的考虑,没有在context.js的create方法中将生成的externalKey挂载到session上

我现在的解决方案是:
1、修改源码,在create方法中,this.session.id = this.externalKey;
2、从cookie中获取,this.session.id = ctx.cookies.get('EGG_SESS', ctx.sessionOptions);

这样做会有什么潜在的问题吗?

我看egg-session-redis中有这样的代码(或扩展egg-session):

app.sessionStore = {
    async get(key) {
      const res = await redis.get(key);
      if (!res) return null;
      return JSON.parse(res);
    },

    async set(key, value, maxAge) {
      maxAge = typeof maxAge === 'number' ? maxAge : ONE_DAY;
      value = JSON.stringify(value);
      await redis.set(key, value, 'PX', maxAge);
    },

    async destroy(key) {
      await redis.del(key);
    },
  };
  • 可以直接调用app.sessionStore.get()进行key的可控性和规则性,而不是自动生成的session id。

如果开启了session-redis,那就意味着session不会存在本地,也就是ctx.session.user='hello'这样原本存在cookie中也会存至redis,对吧?

逻辑是这样的:

如果没有开启redis,即session没有配置store的情况下,egg-session会对session中的内容进行加密,然后以EGG_SESS(默认的)为key,将其存储在cookie里发送到浏览器。下次请求,再将cookie中的内容进行解密,恢复到服务器的session里。

如果开启redis,即session配置了store,egg-session会自动将session内容和配置选项(maxAge,expire等)存入redis中,期间会判断session是否配置了genid函数,如果没有配置,会生成一个随机的extenalKey作为session的key。接下来会将EGG_SESS作为key,externalKey作为value,存入cookie中,响应到前端。

app.sessionStore 只是对redis存取,销毁做的封装,跟sessionId没有关系。

总结:
如果session没有配置store选项,cookie中存的是session加密后的内容。如果session配置了store,cookie中存的是redis中的key(即sessionId)。

不是吧,随机生成的externalKey,和cookie中存储的externalKey,我根本连不起来啊,你是id设置成cookie中的值了吧,不是自动生成的吧?

cookie中的externalKey是随机生成的key加密过的,你需要ctx.cookies.get('EGG_SESS', ctx.sessionOptions);
进行解密

哇,真的耶,多谢大佬指点~

还有一个小问题,如果公司项目的要求redis的key值规范,例如NGCS_SERVICEREQ:20161215001,怎么解决比较好呢?后面数字自定义,:前面的根据项目定义。

config.defaut.js中配置session:

config.session = {
genid: () => {
return 'NGCS_SERVICEREQ:' + 数字;
}
}

this.ctx.session._sessCtx.externalKey

不知是不是各位想要的。。。

this.ctx.session._sessCtx.externalKey

不知是不是各位想要的。。。

竟然藏这么深

Was this page helpful?
0 / 5 - 0 ratings