NodeJS会话控制

在NodeJS中运用Cookie, Session和Token实现会话控制
NodeJS会话控制
Photo by Camille Minouflet / Unsplash

On this page

会话控制基本概念

cookie、session和token

Cookie: Cookie 是存储在用户浏览器上的小型数据片段。它们通常用于存储用户的偏好设置、跟踪用户会话等。服务器在响应中设置 Cookie,浏览器则在随后的每个请求中回传这些 Cookie,直到它们过期。
Session: Session 是在服务器端存储的。它用于保存用户的状态和信息。与 Cookie 不同,Session 数据不会在每个请求中发送给客户端,只有 Session ID 可能会在 Cookie 中存储并传送。
token: token是在客户端存储的,报错了用户的一些关键信息,并通过秘钥加密,每次需要验证用户身份时,token会被发送给服务器,并通过秘钥解码获得里面的关键信息;某种程度上,可以认为token是存储在客户端的session。

session和cookie的关系

在许多 Web 应用中,Session 和 Cookie 通常一起工作来管理用户状态。当用户登录一个网站时,服务器创建一个 Session,并生成一个唯一的 Session ID。这个 Session ID 通常存储在一个 Cookie 中,并发送给用户的浏览器。当用户的浏览器在后续请求中发送这个 Cookie,服务器可以通过 Session ID 来检索和管理用户的 Session 数据。由于token不需要cookie,因此token更适合跨域环境,比如api。

安全性

由于cookie是明文存储,且保存在用户浏览器中,安全性较低,一般通过设置 cookie为HttpOnly(不能通过客户端脚本访问和Secure(仅通过 HTTPS 发送)来提高安全性。
即使如此,也不应该在cookie中存储敏感信息。

NodeJS中应用cookie、session和token

使用cookie

设置cookie

res.cookie('name', 'John', {maxAge: 60*1000*5});
//maxAge: 最大存活时间(单位:毫秒)

获取cookie

let cookie = req.cookies;

删除cookie

res.clearCookie('name');

session

在express框架下的项目需要引入express-session包

npm install express-session

设置session的结构和基本属性

app.use(session({
    //设置cookie的name,默认是:connect.sid
    name: 'sid', 
    //参与加密的字符串(签名)
    secret: 'encryption', 
    //是否为每次请求都设置cookie用来存储session id(如果用户不启用session,则不为其设置cookie)
    saveUninitialized: false, 
    //是否每次重新保存session(每次保存刷新session存活时间)
    resave: true, 
    //session的存储位置(这里使用了connect-mongo包)
    store: mongoStore.create({mongoUrl: 'mongodb://localhost:27017/bilibili'}),
    //httpOnly:开启后前端无法通过JS操作
    cookie: {httpOnly: true, maxAge: 1000 * 60 * 5} 
}));

设置session内容

req.session.username = 'admin';
req.session.uuid = '2dd4bf77-c217-44d2-986e-f4188e5a1580';

销毁session(可以用在用户退出登录时)

req.session.destroy();

token

需要使用jsonwebtoken包

npm install jsonwebtoken

创建token

//三个参数:用户数据、加密字符串、配置对象(生命周期: 单位秒)
let token = jwt.sign({username: 'Mike'}, 'encryption', {expiresIn: 60 * 5})

校验token

jwt.verify(token, 'encryption', (err, data) => {
    if(err){
        console.log('校验失败');
        return;
    }else{
        console.log(data);
    }
})