Session 和 Cookie 的区别、原理与应用场景

目录


HTTP 为什么需要状态

HTTP 协议设计之初就是无状态的。服务器不会保存客户端之前的请求信息,每一次请求都会被独立处理。

无状态本身不是问题,但现代应用越来越依赖用户上下文。登录后,服务器需要识别当前请求对应的用户;购物车需要保存用户之前的操作;后台管理系统需要根据用户身份判断权限。

HTTP 本身不负责维护这些状态,应用需要在协议之上额外实现一套状态管理机制。Cookie 和 Session 就是在这个背景下出现的方案。实际开发中,两者通常配合使用:Cookie 保存身份标识,Session 保存用户状态。

Cookie:浏览器帮你保存一个标识

Cookie 是服务端通过 HTTP 响应头 Set-Cookie 写入浏览器的一小段数据。浏览器收到后会存起来,之后每次向同一个域名发请求,都会自动通过 Cookie 请求头带回去。大多数情况下,开发者甚至不需要手动处理 Cookie,浏览器会自动完成携带过程。

Cookie 的属性在实际项目中最需要关注的是以下三个:

属性 为什么重要
HttpOnly 防止 JavaScript 读取 Cookie,XSS 攻击的第一道防线
Secure 只在 HTTPS 下传输,避免 Cookie 在网络中被嗅探
SameSite 限制跨站请求携带 Cookie,降低 CSRF 风险

其他属性(Domain、Path、Expires)大部分情况下由框架默认处理,不需要特别关注。

Cookie 本身有容量限制,单个不超过 4KB,每个域名下通常最多 50 个。它不是用来存大量数据的,只是一个标识符的载体。实际项目中,Cookie 最常见的用途就是存一个 Session ID。

Session:服务器保存用户状态

Cookie 存在浏览器里,用户能看到、能篡改。直接把用户信息存 Cookie,安全性没法保证。

Session 的思路是:浏览器只存一个不透明的标识符(Session ID),真正的用户数据存在服务端。服务端通过这个 ID 找到对应的用户信息,完成身份识别。

Spring Boot 中使用 Session 非常简单:

java 复制代码
// 登录:把用户信息存入 Session
session.setAttribute("userId", user.getId());
session.setAttribute("username", user.getUsername());

// 后续请求:从 Session 取出用户信息
Long userId = (Long) session.getAttribute("userId");

代码里没有任何 Cookie 操作,但底层 JSESSIONID 这个 Cookie 已经被框架自动处理了。开发者调用 session.setAttribute(),框架负责生成 Session ID、写入 Cookie、下次请求时从 Cookie 取出 ID 并还原 Session 数据。

Session 默认 30 分钟没有活动就会过期,可以在配置里调整:

yaml 复制代码
server:
  servlet:
    session:
      timeout: 60m

把 Cookie 和 Session 串起来,一次完整的登录认证过程是这样的:

整个过程中,Cookie 只是一个"通行证",真正决定"你是谁"的数据在服务端的 Session 里。

单机和分布式下的问题

Session 存在应用服务器的内存里,是 Spring Boot 的默认行为。单机部署没什么问题,但一旦扩展到多台服务器,就出状况了。

用户在 A 服务器登录,Session 存在 A 的内存里。下次请求被负载均衡分到 B 服务器,B 的内存里没有这个 Session,用户就得重新登录。

另外,内存 Session 还有一个问题:服务器重启后,所有用户的登录态全部丢失。对于内部管理系统这类用户量不大、可以接受偶尔重新登录的场景,这不算什么大事。但面向用户的系统,每次发版都要所有用户重新登录,体验就会很差。

Redis Session:解决多实例部署

解决多机 Session 共享最直接的办法:把 Session 从应用服务器剥离出来,存到一个所有服务器都能访问的地方。Redis 是最常见的选择。

Spring Boot 接入 Redis Session 只需要加一个依赖:

yaml 复制代码
# pom.xml 引入 spring-session-data-redis

spring:
  session:
    store-type: redis
  redis:
    host: 192.168.1.100
    port: 6379

引入之后,Session 的读写自动走 Redis,业务代码不需要任何改动。框架会把 Session ID 作为 Redis 的 key,Session 数据序列化后作为 value 存进去,同时设置和 Session 过期时间一致的 TTL。

不过,并不是所有系统都需要 Redis Session。 如果只是一个单体后台管理系统,用户量不大,也不需要多实例部署,Spring Boot 默认的内存 Session 完全够用。Redis Session 解决的核心问题是多实例部署后的 Session 共享,而不是"Session 必须用 Redis"。

复制代码
                      性能      可扩展性      可靠性
内存存储               最快       差           重启丢失
Redis存储              快         好           持久化可选
数据库存储             慢         好           强持久化

数据库理论上也能存 Session,但每次请求都要查一次数据库,读写延迟比 Redis 高一个数量级,实际项目中很少这么做。

JWT:另一种身份认证方式

Session 方案有一个绕不开的问题:服务端要存状态。每多一个在线用户,就多一份存储开销。JWT(JSON Web Token)提供了一种不同的思路。

两者的本质区别很简单:

  • Session:浏览器存 ID,服务器存数据。每次请求,服务器用 ID 查数据。
  • JWT:浏览器存全部信息(编码后的),服务器只负责验证签名。不需要存储。

JWT 不需要服务端存储,看起来更"无状态"。但代价是:服务端失去了对 Token 的控制权。 Session 可以随时在服务端失效(用户改密码、管理员踢人),调一下 session.invalidate() 就行。JWT 发出去之后,服务端不能主动让它失效。要实现"强制下线",要么引入黑名单(又变回有状态了),要么把有效期设得很短,配合 Refresh Token 轮换。

Session 和 JWT 怎么选

场景 推荐方案 原因
传统 Web 应用(单体或少量实例) Session 简单可靠,框架支持完善
多实例部署,需要 Session 共享 Session + Redis 接入成本低,业务代码无改动
无状态 API 服务 JWT 服务端不存状态,水平扩展方便
跨域认证、微服务间身份传递 JWT Token 自包含,不依赖集中存储
需要随时踢人、改密后立即失效 Session 可以主动失效,JWT 做不到这一点

JWT 具备"无状态"特性,但他不一定比 Session 更高级。很多传统 Web 应用依然使用 Session,通过 Redis 保存会话数据,同样可以实现良好的水平扩展。

两者本质上都是在请求到达服务器后,还原用户身份:

  • Session 通过 Session ID 查询 Redis 获取用户信息;
  • JWT 通过解析 Token 并验证签名获取用户信息。

区别只是状态保存的位置不同。选择哪种方案,取决于系统场景,而不是哪个方案听起来更"现代"。

小结

Cookie 在浏览器端存标识,Session 在服务端存数据,两者通过 Session ID 串联完成用户状态的维护。这个方案简单可靠,大多数场景够用。如果需要多实例部署,把 Session 存到 Redis 就能解决共享问题。JWT 是另一种思路,适用于无状态 API 和跨域场景,但它并不是 Session 的"升级版",只是不同的状态管理方式。

相关推荐
深蓝电商API1 个月前
浏览器自动化中的Cookie和Session管理最佳实践
数据采集·cookie·session
学代码的真由酱1 个月前
【自用】接口测试
接口测试·postman·测试·cookie·token鉴权
遇事不決洛必達2 个月前
【爬虫随笔】深入理解 HTTP/HTTPS 协议、接口交互与会话机制
爬虫·网络协议·http·https·session
Irissgwe2 个月前
5-1、HTTP cookie与session
linux·http·cookie·session
tryqaaa_2 个月前
学习日志(五)【php反序列化全加例题】【pop链,字符逃逸,session,伪协议】
android·学习·php·web·pop·session
rising start2 个月前
Web认证机制演进
架构·jwt·session
wangjialelele2 个月前
HTTP Cookie 和 Session
http·cookie·session
随缘而动,随遇而安2 个月前
第九十八篇 工程落地视角:Session/Cookie/Token 原理辨析与大数据实战
大数据·spark·token·cookie·session
曲幽3 个月前
让FastAPI Agent真正记住你:聊聊会话记忆与持久化存储的落地实践
redis·python·postgresql·fastapi·web·chat·async·session·ai agent