Node.js设置与读取Cookie方法详解
时间:2025-09-21 15:14:44 447浏览 收藏
Node.js操作Cookie,关键在于理解HTTP请求头和响应头。不同于浏览器端直接操作`document.cookie`,Node.js需要在服务器端借助如Express等Web框架,并配合`cookie-parser`中间件简化流程。通过`res.cookie()`设置Cookie,`req.cookies`读取Cookie,`res.clearCookie()`清除Cookie。务必重视Cookie的安全性,配置`httpOnly`防止XSS攻击,`secure`确保HTTPS传输,`sameSite`防御CSRF攻击。本文将深入探讨Node.js中Cookie的设置、读取、清除,以及安全属性配置,助你构建更健壮的Web应用。
答案: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学习网公众号也会发布文章相关知识,快来关注吧!
-
501 收藏
-
501 收藏
-
501 收藏
-
501 收藏
-
501 收藏
-
281 收藏
-
390 收藏
-
463 收藏
-
281 收藏
-
233 收藏
-
497 收藏
-
403 收藏
-
230 收藏
-
208 收藏
-
186 收藏
-
416 收藏
-
305 收藏
-
- 前端进阶之JavaScript设计模式
- 设计模式是开发人员在软件开发过程中面临一般问题时的解决方案,代表了最佳的实践。本课程的主打内容包括JS常见设计模式以及具体应用场景,打造一站式知识长龙服务,适合有JS基础的同学学习。
- 立即学习 543次学习
-
- GO语言核心编程课程
- 本课程采用真实案例,全面具体可落地,从理论到实践,一步一步将GO核心编程技术、编程思想、底层实现融会贯通,使学习者贴近时代脉搏,做IT互联网时代的弄潮儿。
- 立即学习 516次学习
-
- 简单聊聊mysql8与网络通信
- 如有问题加微信:Le-studyg;在课程中,我们将首先介绍MySQL8的新特性,包括性能优化、安全增强、新数据类型等,帮助学生快速熟悉MySQL8的最新功能。接着,我们将深入解析MySQL的网络通信机制,包括协议、连接管理、数据传输等,让
- 立即学习 499次学习
-
- JavaScript正则表达式基础与实战
- 在任何一门编程语言中,正则表达式,都是一项重要的知识,它提供了高效的字符串匹配与捕获机制,可以极大的简化程序设计。
- 立即学习 487次学习
-
- 从零制作响应式网站—Grid布局
- 本系列教程将展示从零制作一个假想的网络科技公司官网,分为导航,轮播,关于我们,成功案例,服务流程,团队介绍,数据部分,公司动态,底部信息等内容区块。网站整体采用CSSGrid布局,支持响应式,有流畅过渡和展现动画。
- 立即学习 484次学习