关于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