2026/5/21 15:21:40
网站建设
项目流程
美丽说的网站建设,网站建设售后服务承诺书,百度秒收录的网站,汽车网站图片一、Cookie 和 Session 的存储内容对比
Cookie 中存储什么信息 本质#xff1a;Cookie 只存储一个 Session ID#xff08;会话标识符#xff09;
具体内容#xff1a;
// 一个典型的 Cookie 示例#xff08;开发者工具中查看#xff09;
Name: sessionId
Value: s%3Aa…一、Cookie 和 Session 的存储内容对比Cookie 中存储什么信息本质Cookie 只存储一个 Session ID会话标识符具体内容// 一个典型的 Cookie 示例开发者工具中查看Name:sessionIdValue:s%3Aabc123def456.session_secret_signature// 解码后s:abc123def456.session_secret_signature// s: 是 express-session 的前缀abc123def456 是真正的 session ID// Cookie 的其他关键字段Domain:.example.com// 作用域Path:/// 路径Expires/Max-Age:时间戳// 过期时间Secure:true// 仅 HTTPSHttpOnly:true// 防止 JS 访问SameSite:Lax// 跨站策略为什么 Cookie 只存 ID安全考虑Cookie 存储在用户浏览器可能被窃取大小限制Cookie 一般限制在 4KB网络性能每次请求都会自动发送 CookieSession 中存储什么信息本质Session 存储在服务器端保存用户的完整会话数据具体内容// 一个典型的 session 数据结构存储在 Redis 中{sess:abc123def456:{userId:123456,username:john_doe,email:johnexample.com,roles:[user,admin],loginTime:2024-01-15T10:30:00Z,lastActivity:2024-01-15T11:15:00Z,cart:[{productId:p001,quantity:2},{productId:p002,quantity:1}],preferences:{theme:dark,language:zh-CN,notifications:true},csrfToken:x678y9z0,// 防止 CSRF 攻击_expire:1705313700000// 过期时间戳}}Session 中常见的数据类型认证信息userId, username, email权限信息roles, permissions会话状态loginTime, lastActivity业务数据购物车、表单草稿、临时数据安全令牌csrfToken, oauthState用户偏好主题、语言设置二、存储位置详解Cookie 存储位置位置客户端浏览器中具体存储浏览器存储位置 ├── 内存 CookieSession Cookie │ └── 浏览器关闭即删除 │ ├── 硬盘 Cookie持久 Cookie │ └── 按过期时间存储在硬盘 │ └── 按域和路径组织 ├── example.com/ │ ├── sessionId │ ├── userPref │ └── trackingId └── api.example.com/ └── authToken查看方式浏览器开发者工具Chrome: Application → Storage → CookiesFirefox: Storage → Cookies命令行: document.cookie仅限非 HttpOnly CookieSession 存储位置位置服务器端存储介质// 1. 内存存储默认不推荐生产环境constsessionrequire(express-session);app.use(session({secret:keyboard cat,resave:false,saveUninitialized:true}));// 2. Redis 存储推荐生产环境constRedisStorerequire(connect-redis)(session);app.use(session({store:newRedisStore({host:localhost,port:6379,prefix:sess:,// Redis key 前缀ttl:86400// 过期时间秒}),secret:your-secret}));// 3. 数据库存储MySQL/PostgreSQL/MongoDBconstMongoStorerequire(connect-mongo);app.use(session({store:MongoStore.create({mongoUrl:mongodb://localhost/sessions,ttl:14*24*60*60// 14天}),secret:your-secret}));Redis 中的实际存储结构# 查看所有 sessionredis-cli keyssess:*# 查看具体 session 内容redis-cli getsess:abc123def456# 返回 JSON 字符串包含所有 session 数据三、完整实现流程详解流程图客户端 服务器 | | |--- 1. 登录请求 ---------| | | |-- 2. 创建 session -----| | Set-Cookie: sessionId| | | |--- 3. 带 Cookie 请求 ---| | Cookie: sessionId | | | |-- 4. 验证 session -----| | 返回 session 数据 | | | |--- 5. 后续请求 ---------| | (自动携带 Cookie) | | | |-- 6. 验证/更新 session | | | |--- 7. 登出请求 ---------| | | |-- 8. 销毁 session -----| | 清除 Cookie |详细步骤代码实现constexpressrequire(express);constsessionrequire(express-session);constRedisStorerequire(connect-redis)(session);constappexpress();// 1. Session 中间件配置app.use(session({store:newRedisStore({host:127.0.0.1,port:6379,prefix:sess:,ttl:1800// 30分钟}),name:sessionId,// Cookie 名称默认 connect.sidsecret:complex-secret-key-change-in-production,resave:false,// 避免 session 被覆盖saveUninitialized:false,// 不保存空的 sessioncookie:{// Cookie 相关设置maxAge:30*60*1000,// 30分钟毫秒secure:process.env.NODE_ENVproduction,// 仅 HTTPShttpOnly:true,// 防止 XSSsameSite:lax,// CSRF 防护path:/,// Cookie 路径domain:.example.com// 作用域},rolling:true,// 每次请求重置过期时间genid:function(req){// 生成唯一的 session IDreturnrequire(crypto).randomBytes(16).toString(hex);}}));// 2. 用户登录 - 创建 sessionapp.post(/api/login,async(req,res){const{username,password}req.body;// 验证用户凭证constuserawaitauthenticateUser(username,password);if(user){// 在 session 中存储用户信息req.session.userIduser.id;req.session.usernameuser.username;req.session.rolesuser.roles;req.session.loginTimenewDate();req.session.lastActivitynewDate();// 生成 CSRF tokenreq.session.csrfTokenrequire(crypto).randomBytes(32).toString(hex);// 设置购物车如果之前有if(!req.session.cart){req.session.cart[];}// 发送响应Cookie 会自动通过 Set-Cookie 头发送res.json({success:true,message:登录成功,user:{id:user.id,username:user.username},// 如果需要可以在响应中返回 CSRF tokencsrfToken:req.session.csrfToken});}else{res.status(401).json({success:false,message:认证失败});}});// 3. Session 验证中间件functionrequireAuth(req,res,next){// 检查 session 是否存在且包含用户信息if(!req.session||!req.session.userId){returnres.status(401).json({error:未授权请先登录});}// 更新最后活动时间req.session.lastActivitynewDate();// 检查 CSRF token对于 POST/PUT/DELETE 请求if([POST,PUT,DELETE].includes(req.method)){constclientTokenreq.headers[x-csrf-token]||req.body._csrf;if(clientToken!req.session.csrfToken){returnres.status(403).json({error:CSRF token 无效});}}// 将用户信息附加到请求对象req.user{id:req.session.userId,username:req.session.username,roles:req.session.roles};next();}// 4. 受保护的路由app.get(/api/profile,requireAuth,(req,res){// req.user 已在中间件中设置res.json({user:req.user,loginTime:req.session.loginTime,lastActivity:req.session.lastActivity});});// 5. 更新 session 数据如购物车app.post(/api/cart/add,requireAuth,(req,res){const{productId,quantity}req.body;// 确保购物车存在if(!req.session.cart){req.session.cart[];}// 查找商品是否已在购物车constexistingItemreq.session.cart.find(itemitem.productIdproductId);if(existingItem){existingItem.quantityquantity;}else{req.session.cart.push({productId,quantity});}// 手动保存 session当修改了 session 时req.session.save((err){if(err){console.error(保存 session 失败:,err);returnres.status(500).json({error:服务器错误});}res.json({success:true,cart:req.session.cart});});});// 6. 用户登出 - 销毁 sessionapp.post(/api/logout,(req,res){// 获取 session ID用于清理其他存储constsessionIdreq.session.id;// 销毁 sessionreq.session.destroy((err){if(err){console.error(销毁 session 失败:,err);returnres.status(500).json({error:登出失败});}// 清除客户端的 Cookieres.clearCookie(sessionId,{path:/,domain:.example.com});// 可选清理其他相关存储cleanupSessionData(sessionId);res.json({success:true,message:登出成功});});});// 7. Session 清理任务定时任务functioncleanupExpiredSessions(){// Redis 会自动清理过期的 session基于 TTL// 对于数据库存储可能需要定时任务setInterval(async(){constexpiredSessionsawaitSessionModel.find({expires:{$lt:newDate()}});// 清理过期 sessionawaitSessionModel.deleteMany({_id:{$in:expiredSessions.map(ss._id)}});console.log(清理了${expiredSessions.length}个过期 session);},3600000);// 每小时清理一次}四、关键字段和作用详解Cookie 字段配置表字段值示例作用重要性详细说明NamesessionIdCookie 名称★★★标识 cookie 的键名服务器通过此名称读取 cookie 值Values%3Aabc123加密的 session ID★★★经过编码和签名的 session ID是连接客户端和服务器的关键凭证Domain.example.com作用域★★★指定 cookie 有效的域名. 开头表示所有子域名共享Path/Cookie 有效的路径★★指定 cookie 在网站中的有效路径/ 表示全站有效Expires/Max-Age2024-01-16T10:30:00Z过期时间★★★控制 cookie 的存活时间过期后浏览器自动删除Securetrue仅通过 HTTPS 传输★★★防止 cookie 在明文中传输被窃取生产环境必须启用HttpOnlytrue禁止 JavaScript 访问★★★防止 XSS 攻击窃取 cookie敏感 cookie 必须设置SameSiteLax/StrictCSRF 防护策略★★★控制跨站请求是否携带 cookie有效防止 CSRF 攻击Session 配置字段表字段默认值作用推荐设置详细说明nameconnect.sidCookie 名称自定义名称避免使用默认名称提高安全性防止攻击者猜测secret-签名密钥长且复杂的随机字符串用于签名 session ID防止篡改定期更换resavetrue强制保存 sessionfalse避免每次请求都保存 session减少竞争条件saveUninitializedtrue保存空 sessionfalse不保存未修改的 session节省存储空间cookie.securefalse仅 HTTPS生产环境设为 true确保 cookie 只在安全连接中传输cookie.httpOnlytrue防 XSS始终 true防止 JavaScript 访问敏感 cookiecookie.sameSitefalse跨站策略lax 或 strictstrict完全禁止跨站lax部分允许cookie.maxAgenullCookie 过期时间根据业务设置单位毫秒如 30 分钟30 * 60 * 1000rollingfalse重置过期时间true用户每次活动都延长 session 有效期store内存Session 存储Redis生产环境生产环境必须使用外部存储支持集群部署Session 数据字段表字段名类型存储内容生命周期详细说明userIdString用户唯一标识登录到登出用于关联数据库中的用户记录最关键的字段usernameString用户名登录到登出显示用途避免频繁查询数据库rolesArray用户角色权限登录到登出如 [“user”, “admin”]用于权限控制loginTimeDate登录时间登录到登出记录用户登录时刻用于审计和安全分析lastActivityDate最后活动时间每次请求更新用于判断用户是否活跃实现自动登出csrfTokenStringCSRF 防护令牌每次会话随机生成的 token防止跨站请求伪造攻击cartArray购物车数据会话期间存储用户临时的购物车信息如 [{productId, quantity}]preferencesObject用户偏好会话期间如主题、语言等个性化设置tempDataAny临时数据短期存储表单数据、验证码等临时信息定期清理五、安全最佳实践Cookie 安全设置app.use(session({// ... 其他配置cookie:{secure:true,// 强制 HTTPShttpOnly:true,// 防 XSSsameSite:strict,// 防 CSRFdomain:.yourdomain.com,// 限制域名path:/,// 限制路径maxAge:30*60*1000// 合理过期时间}}));Session 数据清理// 定期清理过期 sessionfunctioncleanOldSessions(){// 删除超过30天未活动的 sessionconstcutoffDate.now()-(30*24*60*60*1000);// Redis 示例redisClient.keys(sess:*,(err,keys){keys.forEach(key{redisClient.get(key,(err,sessionStr){if(sessionStr){constsessionJSON.parse(sessionStr);if(session.lastActivitycutoff){redisClient.del(key);}}});});});}敏感信息处理// 不要在 session 中存储敏感信息// 错误示例req.session.passwordHashuser.passwordHash;// ❌ 危险// 正确做法req.session.userIduser.id;// ✅ 只存储标识符req.session.rolesuser.roles;// ✅ 存储非敏感信息// 敏感信息从数据库实时获取functiongetUserData(req,res,next){if(req.session.userId){User.findById(req.session.userId).select(-password -salt)// 排除敏感字段.then(user{req.useruser;next();});}else{next();}}六、常见问题排查Session 不持久// 检查点 // 1. Cookie 是否设置正确 console.log(Cookie:, req.headers.cookie); // 2. Session 是否保存成功 req.session.test value; req.session.save((err) { if (err) console.error(保存失败:, err); }); // 3. 检查存储连接 redisClient.ping((err, result) { console.log(Redis 连接:, err ? 失败 : 正常); }); 2. 跨域问题 javascript // 前端需要设置 withCredentials fetch(/api/data, { credentials: include // 包含 Cookie }); // 后端需要设置 CORS app.use(cors({ origin: https://frontend.com, credentials: true, // 允许凭证 methods: [GET, POST, PUT, DELETE] }));总结Cookie-Session 机制的核心是Cookie 只存 ID安全、小巧、自动传输Session 存数据完整、安全、服务器可控通过 ID 关联建立客户端和服务器的信任桥梁配合安全策略HttpOnly、Secure、SameSite 多重防护这种机制在传统 Web 应用中表现优秀特别是需要服务器完全控制会话、需要存储大量临时数据、或需要支持服务器主动登出的场景。但在分布式系统和前后端分离架构中需要考虑 Session 共享和扩展性问题