Node.js中如何操作Cookie详解
时间:2025-12-02 17:15:38 342浏览 收藏
本文深入探讨了Node.js中操作Cookie的方法,重点介绍了如何借助Express框架和cookie-parser中间件实现Cookie的设置、读取和清除。文章强调了Cookie安全性的重要性,详细解析了httpOnly、secure、sameSite等关键安全属性,并阐述了它们在防范XSS和CSRF攻击中的作用。此外,还对比了Koa.js、Hapi.js等其他框架处理Cookie的方式,以及纯Node.js环境下的手动操作方法。最后,文章深入分析了Cookie与Session的协同工作机制,阐述了Session在保障用户数据安全方面的优势,并探讨了Session存储面临的挑战,为Node.js开发者提供了全面而实用的Cookie操作指南。
答案:Node.js中操作Cookie需借助Express等框架及cookie-parser中间件,通过res.cookie()设置、req.cookies读取、res.clearCookie()清除,并需配置httpOnly、secure、sameSite等安全属性以防范XSS和CSRF攻击。

在Node.js中操作Cookie,本质上是围绕HTTP请求与响应头进行。我们不会像在浏览器里那样直接去“读写”一个全局的document.cookie对象,而是在服务器端接收来自客户端的Cookie,或向客户端发送设置Cookie的指令。最常见和推荐的方式,是借助像Express.js这样的Web框架,配合其生态中的中间件,如cookie-parser,来简化这一过程。
解决方案
要在Node.js应用中高效且安全地操作Cookie,我们通常会选择一个成熟的Web框架。以Express.js为例,它提供了一套非常直观的API。
首先,你需要安装express和cookie-parser:
npm install express cookie-parser
然后,在你的应用中引入并使用它们:
const express = require('express');
const cookieParser = require('cookie-parser');
const app = express();
const port = 3000;
// 使用cookie-parser中间件。
// 如果你想对Cookie进行签名,可以在这里传入一个秘密字符串(secret)。
// 例如:app.use(cookieParser('your-secret-key'));
app.use(cookieParser());
// 设置Cookie的路由
app.get('/set-cookie', (req, res) => {
// 设置一个简单的Cookie
res.cookie('myCookie', 'helloWorld', { maxAge: 900000, httpOnly: true });
// 设置一个带有更多选项的Cookie
res.cookie('userSession', 'someUserId123', {
expires: new Date(Date.now() + 24 * 3600 * 1000), // 24小时后过期
httpOnly: true, // 重要的安全选项,防止客户端脚本访问
secure: process.env.NODE_ENV === 'production', // 仅在HTTPS连接下发送
sameSite: 'Lax', // 重要的安全选项,防止CSRF攻击
path: '/', // Cookie对所有路径都可用
// domain: '.example.com' // 如果需要跨子域共享
});
res.send('Cookie已设置!');
});
// 获取Cookie的路由
app.get('/get-cookie', (req, res) => {
// cookie-parser会将所有Cookie解析到req.cookies对象上
const myCookie = req.cookies.myCookie;
const userSession = req.cookies.userSession;
if (myCookie) {
res.send(`获取到的myCookie是: ${myCookie},userSession是: ${userSession || '未设置'}`);
} else {
res.send('未找到myCookie。');
}
});
// 清除Cookie的路由
app.get('/clear-cookie', (req, res) => {
// 清除Cookie需要指定其名称和设置时的路径(如果非默认)
res.clearCookie('myCookie');
res.clearCookie('userSession'); // 清除时也要注意path和domain是否匹配
res.send('Cookie已清除!');
});
app.listen(port, () => {
console.log(`服务器运行在 http://localhost:${port}`);
});在这个例子中,res.cookie()方法是设置Cookie的关键。它接受Cookie的名称、值以及一个可选的配置对象。这个配置对象里的参数,比如httpOnly、secure、sameSite等,对于Cookie的安全性和行为至关重要。而req.cookies则是由cookie-parser中间件解析后,提供给我们方便访问客户端发送过来的所有Cookie。清除Cookie则通过res.clearCookie()来实现,它会发送一个过期时间为过去的Set-Cookie头,指示浏览器删除该Cookie。
Node.js中操作Cookie时有哪些常见的安全考量?
在Node.js应用中处理Cookie,安全性绝不是一个可以忽视的环节。我个人觉得,很多开发者,包括我自己在初学时,很容易只关注功能实现而忽略了这些至关重要的安全属性。这些属性的存在,是为了保护用户数据和应用程序免受常见的Web攻击。
httpOnly属性: 这是我首推的、最重要的安全设置之一。当一个Cookie被标记为httpOnly: true时,客户端的JavaScript就无法通过document.cookie来访问它。这意味着,即使你的网站不幸遭受了跨站脚本攻击(XSS),攻击者也无法通过注入恶意JavaScript代码来窃取这个Cookie,从而大大降低了会话劫持的风险。对于存储用户会话ID这类敏感信息的Cookie,httpOnly几乎是必选项。secure属性: 如果你的网站使用了HTTPS(现在应该都是标配了),那么secure: true也是一个必须的设置。它告诉浏览器,这个Cookie只能通过加密的HTTPS连接发送到服务器,而不能通过不安全的HTTP连接发送。这可以防止Cookie在传输过程中被窃听或篡改。在开发环境,我可能会暂时关闭它,但一旦部署到生产环境,这个开关必须打开。sameSite属性: 这个属性是近年来Web安全领域的一个重要进展,主要用于防御跨站请求伪造(CSRF)攻击。它有三个主要值:Lax(默认值,如果未设置): 这是相对宽松的模式。在跨站请求中,只有当用户通过顶部导航(如点击链接)或GET形式的表单提交时,Cookie才会被发送。像标签或等资源加载请求则不会发送Cookie。对于大多数用户体验影响较小的场景,Lax是一个不错的平衡点。Strict: 这是最严格的模式。只有当请求是同站发起的,或者用户直接从目标网站导航过来时,Cookie才会被发送。任何跨站请求(即使是点击链接)都不会发送Cookie。这提供了最强的CSRF保护,但可能会对一些跨站链接的用户体验造成影响,比如从第三方网站跳转到你的网站时,用户可能需要重新登录。None: 允许在所有跨站请求中发送Cookie。但必须同时设置secure: true,否则浏览器会拒绝设置该Cookie。这通常用于需要跨站共享Cookie的场景,例如OAuth认证流程、嵌入式内容或某些API调用。但使用时需要格外小心,确保你的应用程序有其他CSRF保护机制。
过期时间 (
expires或maxAge): 合理设置Cookie的生命周期非常重要。对于会话Cookie(如登录状态),应该设置一个合理的过期时间,而不是让它永久有效。过长的有效期会增加Cookie被窃取后滥用的风险。对于“记住我”功能,也应谨慎设置,并考虑使用刷新令牌等更安全的机制。Cookie签名 (
signed):cookie-parser允许你对Cookie进行签名。这意味着,服务器在发送Cookie时会附加一个数字签名。当Cookie返回服务器时,cookie-parser会验证这个签名。如果Cookie的值在传输过程中被篡改,签名验证就会失败,从而阻止应用程序使用被篡改的Cookie。这并不能加密Cookie内容,但可以防止客户端篡改非敏感数据(例如用户偏好设置)。对于敏感数据,通常不建议直接存入Cookie,而是通过Session ID配合服务器端存储。路径 (
path) 和域名 (domain): 精确控制Cookie的作用域可以限制其暴露范围。例如,将Cookie的path设置为/admin,则该Cookie只会在访问/admin及其子路径时发送。domain属性则可以控制Cookie在哪些子域之间共享。不精确的设置可能会导致Cookie在不必要的上下文中被发送,增加泄露风险。
这些安全考量,我个人认为,是构建健壮Web应用的基础。理解它们并正确应用,远比仅仅知道如何设置和获取Cookie来得重要。
除了Express,Node.js还有哪些库或框架可以方便地处理Cookie?
当然,Node.js的生态非常丰富,处理Cookie的方式也多种多样。虽然Express.js搭配cookie-parser是最常见的组合,但如果你在使用其他框架,或者甚至是在纯Node.js环境下,也有相应的解决方案。
Koa.js: Koa是另一个流行的Node.js Web框架,它以其“洋葱圈”模型和基于
async/await的中间件而闻名。Koa内置了对Cookie的良好支持,无需额外的中间件(尽管有koa-session等可以增强功能)。const Koa = require('koa'); const app = new Koa(); app.use(async (ctx, next) => { // 设置Cookie ctx.cookies.set('koaCookie', 'helloKoa', { maxAge: 900000, httpOnly: true, secure: process.env.NODE_ENV === 'production', sameSite: 'Lax' }); // 获取Cookie const myKoaCookie = ctx.cookies.get('koaCookie'); if (myKoaCookie) { ctx.body = `获取到的koaCookie是: ${myKoaCookie}`; } else { ctx.body = '未找到koaCookie。'; } // 清除Cookie // ctx.cookies.set('koaCookie', null); // 另一种清除方式,将值设为null // ctx.cookies.set('koaCookie', '', { expires: new Date(0) }); // 或者设置过期时间为过去 await next(); }); app.listen(3000, () => { console.log('Koa server running on port 3000'); });Koa的API设计非常简洁,通过
ctx.cookies.set()和ctx.cookies.get()就可以直接操作。我个人觉得,这种设计在现代异步JavaScript中显得更加自然。Hapi.js: Hapi是另一个企业级的Node.js框架,它以其严格的配置和插件系统而著称。Hapi也提供了内置的Cookie处理机制,通常通过其
state配置来管理。const Hapi = require('@hapi/hapi'); const init = async () => { const server = Hapi.server({ port: 3000, host: 'localhost' }); // 配置Cookie state server.state('session', { ttl: 24 * 60 * 60 * 1000, // 1 day isSecure: process.env.NODE_ENV === 'production', isHttpOnly: true, encoding: 'base64json', // 可以对Cookie值进行编码 clearInvalid: false, // 是否清除无效Cookie strictHeader: true, // 严格的header解析 path: '/', sameSite: 'Lax' }); server.route({ method: 'GET', path: '/set-cookie', handler: (request, h) => { return h.response('Cookie set!').state('session', { userId: 'hapiUser123' }); } }); server.route({ method: 'GET', path: '/get-cookie', handler: (request, h) => { const session = request.state.session; if (session && session.userId) { return `User ID from session cookie: ${session.userId}`; } return 'No session cookie found.'; } }); server.route({ method: 'GET', path: '/clear-cookie', handler: (request, h) => { return h.response('Cookie cleared!').unstate('session'); } }); await server.start(); console.log('Hapi Server running on %s', server.info.uri); }; process.on('unhandledRejection', (err) => { console.log(err); process.exit(1); }); init();Hapi通过
server.state()方法定义Cookie的配置,然后在路由处理函数中使用h.response().state()和request.state来设置和获取。它的配置选项非常详尽,适合需要精细控制的场景。纯Node.js (不使用框架): 如果你选择不使用任何框架,直接使用Node.js的
http模块,那么你需要手动解析请求头中的Cookie字段,并手动设置响应头中的Set-Cookie字段。这会涉及到字符串的解析和拼接,相对繁琐且容易出错,这也是为什么我们通常会推荐使用框架或专门的库。const http = require('http'); http.createServer((req, res) => { if (req.url === '/set-cookie') { // 手动设置Set-Cookie头 res.setHeader('Set-Cookie', [ 'pureNodeCookie=helloPureNode; Max-Age=900; HttpOnly; Path=/', 'anotherCookie=value2; Expires=' + new Date(Date.now() + 3600000).toUTCString() + '; Path=/; Secure; SameSite=Lax' ]); res.end('Cookie set by pure Node.js!'); } else if (req.url === '/get-cookie') { // 手动解析Cookie头 const cookieHeader = req.headers.cookie; let cookies = {}; if (cookieHeader) { cookieHeader.split(';').forEach(cookie => { const parts = cookie.split('='); cookies[parts[0].trim()] = parts[1]; }); } res.end(`Cookies from pure Node.js: ${JSON.stringify(cookies)}`); } else { res.end('Hello from pure Node.js!'); } }).listen(3000, () => { console.log('Pure Node.js server running on port 3000'); });这种方式虽然提供了最大的灵活性,但正如你所见,需要处理大量的细节,包括Cookie值的编码、解析,以及各种属性的正确格式化。我个人觉得,除非有非常特殊的需求,否则通常不建议直接采用这种方式。
总的来说,选择哪个库或框架来处理Cookie,很大程度上取决于你项目的整体技术栈。Express和Koa都是非常优秀的选项,它们都提供了强大且易用的Cookie管理功能。
Cookie与Session在Node.js应用中如何协同工作?
在我看来,Cookie和Session的关系,就像是“门票”和“衣帽间凭证”的关系。Cookie是客户端(浏览器)存储的一小段信息,而Session是服务器端存储的用户会话数据。它们通常是协同工作的,Cookie往往被用来承载Session的标识符,而不是Session本身的数据。
核心思想是这样的:
- 用户首次访问或登录时:服务器会生成一个唯一的Session ID,并将这个ID存储在一个Cookie中,然后将这个Cookie发送给客户端。
- 客户端后续请求:客户端在每次发送请求时,都会自动将这个包含Session ID的Cookie发送回服务器。
- 服务器端识别:服务器接收到请求后,会从Cookie中提取Session ID,然后根据这个ID去查找服务器端存储的对应Session数据。
在Node.js应用中,实现这种协同工作最常见的方式是使用express-session这样的中间件(如果你使用Express.js)。
const express = require('express');
const session = require('express-session'); // 注意这里是express-session,不是cookie-parser
const app = express();
const port = 3000;
// 配置session中间件
app.use(session({
secret: 'mySuperSecretKeyForSigningSessionCookie', // 必须提供一个秘密字符串来签名Session ID Cookie
resave: false, // 强制session保存到session store中,即使在请求中没有被修改
saveUninitialized: false, // 强制未初始化的session保存到session store中
cookie: {
maxAge: 1000 * 60 * 60 * 24, // Session Cookie的有效期,例如24小时
httpOnly: true,
secure: process.env.NODE_ENV === 'production',
sameSite: 'Lax',
}
// store: new RedisStore({ client: redisClient }) // 如果需要将session存储到外部数据库,如Redis
}));
// 登录路由,设置session
app.get('/login', (req, res) => {
req.session.userId = 'user123';
req.session.username = 'Alice';
req.session.loggedIn = true;
res.send('登录成功,Session已设置!');
});
// 获取session数据的路由
app.get('/profile', (req, res) => {
if (req.session.loggedIn) {
res.send(`欢迎回来,${req.session.username}!你的ID是:${req.session.userId}`);
} else {
res.status(401).send('请先登录。');
}
});
// 登出路由,销毁session
app.get('/logout', (req, res) => {
req.session.destroy((err) => {
if (err) {
return res.status(500).send('登出失败。');
}
res.send('登出成功,Session已销毁!');
});
});
app.listen(port, () => {
console.log(`服务器运行在 http://localhost:${port}`);
});在这个例子中:
express-session中间件会自动处理Session ID的生成、存储到Cookie、以及从Cookie中读取Session ID并加载对应的Session数据。req.session对象就是服务器端存储的用户会话数据。你可以在这里存储任何非敏感的用户状态信息,例如用户ID、用户名、登录状态、购物车内容等。secret选项至关重要,它用于签名Session ID Cookie,防止客户端篡改。cookie选项则允许你配置Session ID Cookie本身的各种属性,如maxAge、httpOnly、secure和sameSite,这些都和前面提到的Cookie安全考量一致。
为什么Session比直接在Cookie中存储所有数据更安全? 我个人认为,Session的优势在于它将大部分敏感数据保留在服务器端。如果直接把所有用户数据都塞进Cookie,不仅有大小限制,而且如果Cookie没有加密或签名不当,客户端就可能篡改或窃取这些数据。Session ID只是一个不包含实际信息的随机字符串,即使它被窃取,攻击者也只能通过它访问服务器上存储的数据,而无法直接从Cookie中获取敏感信息。
Session的权衡: 虽然Session提供了更好的安全性,但它也有其代价。
- 服务器资源消耗: 每个活动会话都会占用服务器内存(如果使用默认的内存存储),这在高并发场景下可能成为瓶颈。
- 分布式部署挑战: 在负载均衡的集群环境中,需要一个共享的Session存储(如Redis、MongoDB或数据库)来确保用户在不同服务器之间切换时,其会话数据仍然可用。这就是为什么
express-session提供了store选项。
总而言之,Cookie和Session是Web应用中管理用户状态的两种互补机制。Cookie负责在客户端和服务器之间传递一个标识符,而Session则在服务器端维护这个标识符所代表的完整用户状态。理解它们各自的职责和协同方式,对于构建安全、可扩展的Node.js应用至关重要。
文中关于的知识介绍,希望对你的学习有所帮助!若是受益匪浅,那就动动鼠标收藏这篇《Node.js中如何操作Cookie详解》文章吧,也可关注golang学习网公众号了解相关技术文章。
-
502 收藏
-
501 收藏
-
501 收藏
-
501 收藏
-
501 收藏
-
259 收藏
-
451 收藏
-
451 收藏
-
200 收藏
-
306 收藏
-
249 收藏
-
366 收藏
-
437 收藏
-
499 收藏
-
171 收藏
-
195 收藏
-
393 收藏
-
- 前端进阶之JavaScript设计模式
- 设计模式是开发人员在软件开发过程中面临一般问题时的解决方案,代表了最佳的实践。本课程的主打内容包括JS常见设计模式以及具体应用场景,打造一站式知识长龙服务,适合有JS基础的同学学习。
- 立即学习 543次学习
-
- GO语言核心编程课程
- 本课程采用真实案例,全面具体可落地,从理论到实践,一步一步将GO核心编程技术、编程思想、底层实现融会贯通,使学习者贴近时代脉搏,做IT互联网时代的弄潮儿。
- 立即学习 516次学习
-
- 简单聊聊mysql8与网络通信
- 如有问题加微信:Le-studyg;在课程中,我们将首先介绍MySQL8的新特性,包括性能优化、安全增强、新数据类型等,帮助学生快速熟悉MySQL8的最新功能。接着,我们将深入解析MySQL的网络通信机制,包括协议、连接管理、数据传输等,让
- 立即学习 500次学习
-
- JavaScript正则表达式基础与实战
- 在任何一门编程语言中,正则表达式,都是一项重要的知识,它提供了高效的字符串匹配与捕获机制,可以极大的简化程序设计。
- 立即学习 487次学习
-
- 从零制作响应式网站—Grid布局
- 本系列教程将展示从零制作一个假想的网络科技公司官网,分为导航,轮播,关于我们,成功案例,服务流程,团队介绍,数据部分,公司动态,底部信息等内容区块。网站整体采用CSSGrid布局,支持响应式,有流畅过渡和展现动画。
- 立即学习 485次学习