likes
comments
collection
share

关于eggjs中cookie 与 session的一些问题

作者站长头像
站长
· 阅读数 11

首先需要明白一个概念: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

eggjscookie 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 代表了存储 SessionCookie 键值对的 key 是什么,如下图所示:

关于eggjs中cookie 与 session的一些问题

当用户发起登录后,我们验证用户名和密码正确后,设置session,如下:

const { name, pwd } = ctx.request.body;
// 设置 Session
ctx.session.userId = '123';
ctx.session.userName = name;

此时,框架就会自动的会在响应头上加上set-cookie

关于eggjs中cookie 与 session的一些问题

接着,用户发起其他请求,就会带上刚才的cookie,框架就会自动的在上下文中ctx.session加上解密后的cookie信息,拿到用户信息后就知道是哪个用户了。

const { ctx } = this;
const userId = ctx.session.userId;
const userName = ctx.session.userName;

用户点击登出的时候,服务端只需要设置为:

ctx.session = null;

框架就会重新设置set-cookie,且值为空:

关于eggjs中cookie 与 session的一些问题

修改用户 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
评论
请登录