Session / 会话

WEB 请求中经常通过 session 来维持会话的,框架通过 think-session 和 Adapter 来支持 session 功能。

配置扩展和 Adapter

修改扩展配置文件 src/config/extend.js(多模块项目为 src/common/config/extend.js),添加下面的配置:

const session = require('think-session');
module.exports = [
  session
]

修改 Adapter 配置文件 src/config/adapter.js(多模块项目为 src/common/config/adapter.js),添加下面的配置:

const fileSession = require('think-session-file');

exports.session = {
  type: 'file',
  common: {
    cookie: {
      name: 'thinkjs',
      keys: ['signature key'],
      signed: true
    }
  },
  file: {
    handle: fileSession,
    sessionPath: path.join(think.ROOT_PATH, 'runtime/session')
  }
}

支持的 session 类型列表见:https://github.com/thinkjs/think-awesome#session,其中 cookie 选项为 session 设置 cookie 时的配置项,会和 think.config('cookie') 值进行合并,name 字段值为 session 对应 cookie 的名字。

注入的方法

添加 think-session 扩展后,会注入 ctx.sessioncontroller.session 方法,其中 controller.session 是 ctx.session 方法的包装,会读取当前请求下对应的配置。

读取 session

module.exports = class extends think.Controller {
  // 获取 session
  async indexAction() {
    const data = await this.session('name');
  }
}

设置 session

module.exports = class extends think.Controller {
  // 设置 session
  async indexAction() {
    await this.session('name', 'value');
  }
}

删除 session

module.exports = class extends think.Controller {
  // 删除整个 session
  async indexAction() {
    await this.session(null);
  }
}

常见问题

一个请求下能操作不同类型的 session 么?

不能。session 数据是异步更新的,所以一个请求下只允许使用一种 session。

session 数据是怎么同步的?

当 session 数据改变后,并不会立即更新到 session 容器里(为了性能考虑),而是在请求结束时统一更新。

this.ctx.res.once('finish', () => {
  // 在请求结束时将 session flush 到存储容器中
});

如何获取 session 对应 cookie 的值?

session 对应 cookie 的值是不能手工设置的,而是框架自动生成,生成方式为 think.uuid。后续 Action 中可以通过 this.cookie('thinkjs')获取到该 cookie (thinkjs 为 session 对应 cookie 的字段名称)。

如何限制同一个帐号在不同的端登录?

有些情况下,只允许一个帐号在一个端下登录,如果换了一个端,需要把之前登录的端踢下线(默认情况下,同一个帐号可以在不同的端下同时登录的)。这时候可以借助一个服务保存用户唯一标识和 session cookie 值的对应关系,如果同一个用户,但 cookie 不一样,则不允许登录或者把之前的踢下线。如:

// 当用户登录成功后
const cookie = this.cookie('thinkjs');
const uid = userInfo.id;
await this.redis.set(`uid-${uid}`, cookie);

// 请求时,判断 session cookie 值是否相同
const userInfo = await this.session('userInfo');
const cookie = this.cookie('thinkjs');
const saveCookie = await this.redis.get(`uid-${userInfo.id}`);
if(saveCookie && saveCookie !== cookie) {
  // 不是最近一台登录的设备
}
如发现文档中的错误,请点击这里修改本文档,修改完成后请 pull request,我们会尽快合并、更新。