news 2026/5/9 2:25:17

Cookie 与 Session 的区别及 Cookie 传输机制

作者头像

张小明

前端开发工程师

1.2k 24
文章封面图
Cookie 与 Session 的区别及 Cookie 传输机制

1.核心区别对比表

特性CookieSession
存储位置客户端浏览器服务器端
存储内容文本数据(key-value)对象数据(通常有Session ID)
安全性较低(可被篡改)较高(服务器控制)
存储大小每个域名通常 ≤ 4KB仅受服务器限制
生命周期可设置过期时间通常浏览器关闭或超时
性能影响每次请求自动携带服务器需要查询存储
跨域支持有限制(同源策略)不受限制(服务器间)

2.Cookie 详解

2.1Cookie 的结构

Set-Cookie: name=value; Expires=Wed, 21 Oct 2025 07:28:00 GMT; Max-Age=3600; Domain=example.com; Path=/; Secure; HttpOnly; SameSite=Strict

2.2Cookie 的属性和作用

const cookieAttributes = { // 基础属性 name: "sessionId", value: "abc123xyz", // 有效期控制 expires: "2025-12-31T23:59:59Z", // 绝对时间 maxAge: 3600, // 相对时间(秒) // 作用域控制 domain: ".example.com", // 可作用于子域名 path: "/api", // 指定路径 // 安全属性 secure: true, // 仅HTTPS传输 httpOnly: true, // 禁止JavaScript访问 sameSite: "Strict", // 防止CSRF // 新属性 partitioned: true, // 第一方隔离 priority: "High" // 存储优先级 };

2.3Cookie 如何传递给后端

方式1:浏览器自动携带
# 请求头中的 Cookie GET /api/user HTTP/1.1 Host: example.com Cookie: sessionId=abc123xyz; username=johndoe; theme=dark Connection: keep-alive
方式2:手动设置(JavaScript)
// 1. 设置 Cookie document.cookie = "username=john; path=/; max-age=3600"; // 2. 读取 Cookie const cookies = document.cookie.split(';').reduce((acc, cookie) => { const [key, value] = cookie.trim().split('='); acc[key] = value; return acc; }, {}); // 3. 删除 Cookie(设置过期时间) document.cookie = "username=; expires=Thu, 01 Jan 1970 00:00:00 UTC; path=/;"; // 4. 在请求中手动添加 Cookie fetch('/api/data', { headers: { 'Cookie': 'sessionId=abc123' } });
方式3:服务器端设置
// Node.js Express app.get('/login', (req, res) => { // 设置 Cookie res.cookie('sessionId', 'abc123', { maxAge: 24 * 60 * 60 * 1000, // 24小时 httpOnly: true, secure: process.env.NODE_ENV === 'production', sameSite: 'strict' }); // 设置多个 Cookie res.cookie('user', JSON.stringify({ id: 1, name: 'John' }), { maxAge: 900000 }); });

3.Session 详解

3.1Session 工作原理

客户端 服务器 | | |--- 1. 登录请求 ---------->| | | | 2. 创建Session ---------| | sessionId = "abc123" | | sessionStore[sessionId] = {userId: 1} | | | |<-- 3. 返回Set-Cookie -----| | Set-Cookie: sessionId=abc123 | | |--- 4. 携带Cookie请求 ----->| | Cookie: sessionId=abc123 | | | | 5. 验证Session ---------| | user = sessionStore[sessionId] | | |<-- 6. 返回数据 ------------|

3.2Session 存储方式

// 1. 内存存储(不推荐生产环境) const sessionStore = new Map(); // 2. Redis 存储(推荐) const redisSessionStore = { async set(sessionId, sessionData) { await redisClient.set( `session:${sessionId}`, JSON.stringify(sessionData), 'EX', 3600 // 1小时过期 ); }, async get(sessionId) { const data = await redisClient.get(`session:${sessionId}`); return data ? JSON.parse(data) : null; } }; // 3. 数据库存储 const dbSessionStore = { async set(sessionId, sessionData) { await db.sessions.upsert({ where: { sessionId }, update: { data: JSON.stringify(sessionData), expiresAt: new Date(Date.now() + 3600000) }, create: { sessionId, data: JSON.stringify(sessionData), expiresAt: new Date(Date.now() + 3600000) } }); } };

4.完整登录流程示例

4.1基于 Session 的认证流程

// 前端代码(React) const LoginForm = () => { const [credentials, setCredentials] = useState({ username: '', password: '' }); const handleLogin = async () => { try { // 1. 发送登录请求 const response = await fetch('/api/login', { method: 'POST', headers: { 'Content-Type': 'application/json', }, body: JSON.stringify(credentials), credentials: 'include' // 关键!允许携带Cookie }); // 2. 检查响应状态 if (response.ok) { // 3. 后续请求会自动携带Cookie const userData = await fetch('/api/user/profile', { credentials: 'include' }).then(res => res.json()); console.log('登录成功', userData); } } catch (error) { console.error('登录失败', error); } }; return ( <form onSubmit={(e) => { e.preventDefault(); handleLogin(); }}> <input value={credentials.username} onChange={(e) => setCredentials({...credentials, username: e.target.value})} /> <input type="password" value={credentials.password} onChange={(e) => setCredentials({...credentials, password: e.target.value})} /> <button type="submit">登录</button> </form> ); };

4.2后端代码(Node.js + Express)

const express = require('express'); const session = require('express-session'); const RedisStore = require('connect-redis')(session); const redis = require('redis'); const app = express(); // 1. 创建Redis客户端 const redisClient = redis.createClient({ host: 'localhost', port: 6379 }); // 2. 配置Session中间件 app.use(session({ store: new RedisStore({ client: redisClient }), secret: 'your-secret-key', resave: false, saveUninitialized: false, cookie: { maxAge: 24 * 60 * 60 * 1000, // 24小时 httpOnly: true, secure: process.env.NODE_ENV === 'production', sameSite: 'strict' } })); // 3. 登录路由 app.post('/api/login', (req, res) => { const { username, password } = req.body; // 验证用户 const user = authenticateUser(username, password); if (user) { // 将用户信息存入session req.session.userId = user.id; req.session.username = user.username; req.session.role = user.role; // 设置登录时间 req.session.loginTime = new Date(); res.json({ success: true, message: '登录成功', user: { id: user.id, username: user.username } }); } else { res.status(401).json({ success: false, message: '登录失败' }); } }); // 4. 受保护的路由 app.get('/api/user/profile', (req, res) => { // 检查session if (!req.session.userId) { return res.status(401).json({ error: '未登录' }); } // 获取用户数据 const userData = getUserById(req.session.userId); res.json(userData); }); // 5. 登出 app.post('/api/logout', (req, res) => { req.session.destroy((err) => { if (err) { return res.status(500).json({ error: '登出失败' }); } // 清除客户端Cookie res.clearCookie('connect.sid'); res.json({ success: true, message: '已登出' }); }); });

5.Cookie 传输的常见问题与解决方案

5.1跨域请求携带 Cookie

// 前端设置 fetch('https://api.example.com/data', { method: 'GET', credentials: 'include', // 关键!允许发送Cookie headers: { 'Content-Type': 'application/json', } }); // 后端设置(CORS配置) app.use(cors({ origin: 'https://frontend.com', // 允许的源 credentials: true, // 允许携带凭证 methods: ['GET', 'POST', 'PUT', 'DELETE'], allowedHeaders: ['Content-Type', 'Authorization'] })); // 或者手动设置响应头 app.use((req, res, next) => { res.header('Access-Control-Allow-Origin', 'https://frontend.com'); res.header('Access-Control-Allow-Credentials', 'true'); res.header('Access-Control-Allow-Headers', 'Content-Type, Authorization'); next(); });

5.2SameSite 属性详解

// 不同SameSite策略的影响 const sameSiteStrategies = { Strict: { description: "完全禁止跨站Cookie", useCase: "银行、支付等敏感操作", example: "SameSite=Strict" }, Lax: { description: "允许部分安全的跨站请求(如导航)", useCase: "默认值,适合大多数场景", example: "SameSite=Lax", allowedRequests: [ "从外部链接点击进入(GET)", "页面刷新", "预加载请求" ] }, None: { description: "允许所有跨站请求", useCase: "需要跨站功能的场景(如SSO)", requirements: [ "必须同时设置Secure属性", "必须使用HTTPS" ], example: "SameSite=None; Secure" } };

5.3Cookie 大小限制与优化

// 优化策略 const cookieOptimization = { // 1. 减少Cookie数量 strategies: [ "合并多个Cookie为一个", "使用Session替代大量Cookie", "将非必要数据存储到LocalStorage" ], // 2. 压缩Cookie值 compressCookie: (data) => { const jsonStr = JSON.stringify(data); // 使用base64编码压缩 return Buffer.from(jsonStr).toString('base64'); }, // 3. 按需发送Cookie setupCookies: () => { // 主域名设置通用Cookie document.cookie = "theme=dark; domain=.example.com; path=/"; // 子域名设置特定Cookie document.cookie = "api_token=xyz; domain=api.example.com; path=/"; // 特定路径设置Cookie document.cookie = "cart_items=3; path=/shop"; }, // 4. 定期清理过期Cookie cleanupCookies: () => { const cookies = document.cookie.split(';'); cookies.forEach(cookie => { const [name, value] = cookie.trim().split('='); // 检查并删除过期Cookie if (isCookieExpired(name)) { document.cookie = `${name}=; expires=Thu, 01 Jan 1970 00:00:00 GMT; path=/`; } }); } };

6.现代认证方案对比

6.1传统 Session vs JWT

// JWT 认证流程 const jwtAuth = { login: async (username, password) => { // 1. 验证用户 const user = await validateUser(username, password); // 2. 生成JWT const token = jwt.sign( { userId: user.id, role: user.role }, process.env.JWT_SECRET, { expiresIn: '24h' } ); // 3. 可选:存储在HttpOnly Cookie中 res.cookie('jwt', token, { httpOnly: true, secure: true, sameSite: 'strict' }); return token; }, // 验证中间件 authenticate: (req, res, next) => { // 从Cookie或Authorization头获取token const token = req.cookies.jwt || req.headers.authorization?.split(' ')[1]; if (!token) { return res.status(401).json({ error: '未授权' }); } try { const decoded = jwt.verify(token, process.env.JWT_SECRET); req.user = decoded; next(); } catch (error) { return res.status(401).json({ error: 'Token无效' }); } } };

6.2Session、JWT、OAuth 2.0 对比

Session-Based: 优点: 服务端可控,安全性高,可随时撤销 缺点: 服务器有状态,扩展性差,CSRF风险 适用: 传统Web应用,管理后台 JWT (Token-Based): 优点: 无状态,扩展性好,适合微服务 缺点: Token一旦签发无法撤销,需短有效期 适用: 移动App,SPA,API服务 OAuth 2.0: 优点: 第三方登录,权限委托,标准化 缺点: 实现复杂,依赖第三方 适用: 社交登录,API授权

7.安全最佳实践

7.1Cookie 安全设置

// 安全的Cookie配置 const secureCookieConfig = { // 生产环境必须启用 secure: process.env.NODE_ENV === 'production', // 防止XSS攻击 httpOnly: true, // 防止CSRF攻击 sameSite: 'strict', // 或 'lax' // 限制作用域 domain: 'example.com', // 不设置点前缀,限制精确域名 path: '/api', // 限制路径 // 过期时间 maxAge: 15 * 60 * 1000, // 15分钟(会话类Cookie) // 签名防止篡改 signed: true }; // Express中应用 res.cookie('sessionId', sessionId, secureCookieConfig);

7.2防御常见攻击

// 1. 防御CSRF app.use(csrf({ cookie: { key: '_csrf', path: '/', httpOnly: true, secure: process.env.NODE_ENV === 'production', sameSite: 'strict' } })); // 2. 设置安全响应头 app.use(helmet()); // 3. 限制Cookie数量 app.use((req, res, next) => { const cookieCount = req.headers.cookie?.split(';').length || 0; if (cookieCount > 10) { return res.status(400).json({ error: 'Too many cookies' }); } next(); });

8.调试与测试工具

8.1浏览器开发者工具

// 查看和管理Cookie console.log(document.cookie); // Chrome DevTools中: // 1. Application → Storage → Cookies // 2. Network → 查看请求头中的Cookie // 3. 手动修改和删除Cookie进行测试

8.2命令行工具

# 查看网站Cookie curl -v https://example.com # 发送带Cookie的请求 curl -H "Cookie: sessionId=abc123" https://api.example.com/data # 测试Cookie属性 # 使用浏览器插件:EditThisCookie, Cookie-Editor

总结

选择建议:

  • 传统Web应用:使用 Session + HttpOnly Cookie

  • SPA + API:使用 JWT + HttpOnly Cookie 或 Authorization Header

  • 第三方集成:使用 OAuth 2.0

  • 敏感操作:启用双重认证,Session + 短期Token

关键要点:

  1. Cookie 自动传输:浏览器自动在请求头中携带

  2. Session 需要Cookie:Session ID通过Cookie传递

  3. 安全第一:始终使用 HttpOnly + Secure + SameSite

  4. 跨域注意:需要正确配置CORS和Cookie属性

  5. 性能考虑:避免过多Cookie,合理设置过期时间

现代趋势:

  • 逐渐转向无状态认证(JWT)

  • SameSite=Lax 成为默认

  • 第一方Cookie隔离(Partitioned属性)

  • 减少对第三方Cookie的依赖

版权声明: 本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若内容造成侵权/违法违规/事实不符,请联系邮箱:809451989@qq.com进行投诉反馈,一经查实,立即删除!
网站建设 2026/5/3 18:09:42

基于单片机的智能窗帘控制系统设计与实现

一、设计背景与核心需求 随着智能家居技术的发展&#xff0c;传统窗帘的手动操作已无法满足现代生活对便捷性、舒适性和节能性的需求。高层住宅大尺寸窗帘拉动费力、忘记关窗导致风雨侵入、光照过强影响室内环境等问题频发。基于单片机的智能窗帘控制系统&#xff0c;通过环境感…

作者头像 李华
网站建设 2026/5/3 5:45:08

Java 应用提供对接第三方接口的优雅高级写法

一、真正的高手,不是“调通接口”,而是“设计边界” 对接第三方接口,看似只是发个请求、拿个 JSON,但背后其实是——系统边界的协作与防御设计。 你面对的不是自己可控的代码,而是一个随时可能“变脸”的外部世界: 对方文档写着“此字段必传”,实际却返回 null 测试环境…

作者头像 李华
网站建设 2026/5/3 14:38:43

基于S7 - 1200 PLC的工业冷库等控制系统漫谈

基于S7-1200 PLC工业冷库控制系统 基于PLC的空调控制系统设计。 基于PLC的工业空调机组设计。基于PLC的冷风机组系统设计带解释的梯形图接线图原理图图纸&#xff0c;io分配&#xff0c;组态画面在工业领域&#xff0c;对于温度的精准控制至关重要&#xff0c;无论是冷库、空调…

作者头像 李华
网站建设 2026/4/30 19:06:48

鸿蒙Electron应用商业化效果评估:数据驱动的增长闭环

基于前文对商业化落地的探讨&#xff0c;本次将聚焦“鸿蒙Electron应用商业化效果评估体系”&#xff0c;从“核心指标构建、数据采集分析、优化迭代闭环”三个维度&#xff0c;提供可量化、可落地的评估方案&#xff0c;帮助开发者精准判断商业化健康度并高效优化。 鸿蒙Elect…

作者头像 李华
网站建设 2026/5/4 7:03:14

网络安全靶场推荐,让你通过实操能快速提升实战技能!

前言 自学网络安全知识&#xff0c;具备一定的理论基础&#xff0c;缺乏实战经验&#xff0c;想去网络靶场体验一下&#xff0c;通过实操能快速提升实战技能&#xff01; 可推荐的网络靶场&#xff1a; 1、春秋云境.com&#xff1a;平台涵盖350CVE靶标和10套大型仿真场景&am…

作者头像 李华