关于eggjs中cookie 与 session的一些问题
首先需要明白一个概念:cookie在 Web 应用中经常承担标识请求方身份的功能,比如userId=sdud12df,为了保密这个sdud12df是一个随机字符串,不能是数据库中某个值。当发送请求后,服务器获取到这个userId,然后去session里面找关于这个用户的相关信息,比如真实的userId等,所以session就是一个存储用户信息的场所。
那 session 既然是一个存储用户信息的场所,那它可以用一个全局的变量才存储,也可以存储在redis这样的内存数据库中。同时,因为服务是多进程部署,所以session一般是用redis来保存。
那在eggjs中,session存放在什么位置呢?
session的存放位置
大部分应用session是放在redis等外部存储器中的,但是eggjs默认把session存放在cookie中,即存放在浏览器中,用户每次请求我们网站的时候都会带上这个 cookie,我们在服务端解密后就可以获取到用户的身份信息了。
这里就比较有意思了,session 居然存储在浏览器中的cookie中,而且是通过加密的,用户请求时服务端通过解密就可以获取用户的信息,从而知道是哪个用户在发送请求了。
session 如果存放在 cookie 中,但是如果我们的 session 对象过于庞大,就会带来一些额外的问题:
- 浏览器通常都有限制最大的
cookie长度,当设置的session过大时,浏览器可能拒绝保存。 cookie在每次请求时都会带上,当session过大时,每次请求都要额外带上庞大的cookie信息。
如果一旦选择了将 session 存入到外部存储中,就意味着系统将强依赖于这个外部存储,当它挂了的时候,我们就完全无法使用 session 相关的功能了。
因此更推荐大家只将必要的信息存储在 session 中,保持 session 的精简并使用默认的 cookie 存储,用户级别的缓存不要存储在 session 中。
eggjs中cookie session的使用
eggjs框架内置了 Session 插件,不需要我们重新安装。
首先需要对 session 进行配置:
config.session = {
key: 'PENG_SESS', // 可以修改
maxAge: 24 * 3600 * 1000, // 1 天
httpOnly: true,
// 验签
signed: true,
// 加密
encrypt: true,
// 在发现当用户 Session 的有效期仅剩下最大有效期一半的时候,重置 Session 的有效期。
renew: true,
};
key 代表了存储 Session 的 Cookie 键值对的 key 是什么,如下图所示:

当用户发起登录后,我们验证用户名和密码正确后,设置session,如下:
const { name, pwd } = ctx.request.body;
// 设置 Session
ctx.session.userId = '123';
ctx.session.userName = name;
此时,框架就会自动的会在响应头上加上set-cookie:

接着,用户发起其他请求,就会带上刚才的cookie,框架就会自动的在上下文中ctx.session加上解密后的cookie信息,拿到用户信息后就知道是哪个用户了。
const { ctx } = this;
const userId = ctx.session.userId;
const userName = ctx.session.userName;
用户点击登出的时候,服务端只需要设置为:
ctx.session = null;
框架就会重新设置set-cookie,且值为空:

修改用户 session 失效时间
虽然在 session 的配置中有一项是 maxAge,但是它只能全局设置 session 的有效期,我们经常可以在一些网站的登录页上看到有 记住我 的选项框,勾选之后可以让登录用户的 session 有效期更长。这种针对特定用户的 session 有效时间设置我们可以通过 ctx.session.maxAge= 来实现。
const ms = require('ms');
class UserController extends Controller {
async login() {
const ctx = this.ctx;
const { username, password, rememberMe } = ctx.request.body;
const user = await ctx.loginAndGetUser(username, password);
// 设置 Session
ctx.session.user = user;
// 如果用户勾选了 `记住我`,设置 30 天的过期时间
if (rememberMe) ctx.session.maxAge = ms('30d');
}
}
还有一种情况,当用户请求没有导致 session 被修改时,框架都不会延长 session 的有效期,但是在有些场景下,我们希望用户如果长时间都在访问我们的站点,则延长他们的 session 有效期,不让用户退出登录态。
框架提供了一个 renew 配置项用于实现此功能,它会在发现当用户 session 的有效期仅剩下最大有效期一半的时候,重置 session 的有效期。
总结
使用eggjs开发过程中,因为内置了cookie session相关的插件,使得用户登录变得简单高效。
如果要查看具体信息,可以看下官网Cookie 与 Session
转载自:https://juejin.cn/post/7270072543989907493