0%

会话管理

会话管理:Cookie 与 Session 详解

HTTP 协议是无状态的,即服务器无法自动关联多次请求是否来自同一客户端。为了实现用户登录状态保持、购物车等功能,需要通过CookieSession技术维持客户端与服务器之间的会话状态。本文将详细解析这两种技术的原理、使用方法及核心区别。

会话管理的必要性

无状态的 HTTP 协议导致服务器无法识别连续请求的关联性。例如:

  • 用户在电商网站添加商品到购物车后,切换页面时服务器无法记住之前的选择;
  • 用户登录后,访问其他页面时服务器无法验证其已登录状态。

会话管理技术通过在客户端或服务器端存储标识信息,将多次请求关联为一个 “会话”,从而实现状态保持。

Cookie:客户端存储的会话标识

Cookie 是服务器发送给客户端的小型文本数据,由浏览器存储在本地(文件或内存中)。当客户端再次访问同一服务器时,浏览器会自动携带 Cookie 到请求中,使服务器识别客户端身份。

  1. 服务器发送 Cookie:服务器在响应中通过 Set-Cookie 头字段将 Cookie 发送给浏览器。
    示例响应头:Set-Cookie: userId=123; Path=/; Max-Age=3600
  2. 浏览器存储 Cookie:浏览器将 Cookie 保存到本地(内存或磁盘,取决于有效期)。
  3. 客户端携带 Cookie:客户端再次请求同一服务器时,通过 Cookie 头字段将 Cookie 回传给服务器。
    示例请求头:Cookie: userId=123
1
2
3
4
5
6
7
8
9
10
11
12
// 创建 Cookie(键值对形式)
Cookie cookie = new Cookie("username", "zhangsan");

// 设置属性(可选)
cookie.setMaxAge(3600); // 有效期 3600 秒(1 小时),0 表示立即删除,-1 表示会话结束后删除
cookie.setPath("/"); // 适用路径(/ 表示全站有效)
cookie.setDomain(".example.com"); // 适用域名(跨子域共享,如 www.example.com 和 user.example.com)
cookie.setSecure(true); // 仅在 HTTPS 连接中发送
cookie.setHttpOnly(true); // 禁止 JavaScript 访问(防止 XSS 攻击)

// 发送到客户端(添加到响应中)
response.addCookie(cookie);
1
2
3
4
5
6
7
8
9
10
11
12
// 获取所有 Cookie(返回数组,可能为 null)
Cookie[] cookies = request.getCookies();

if (cookies != null) {
for (Cookie cookie : cookies) {
String name = cookie.getName(); // 获取键
String value = cookie.getValue(); // 获取值
if ("username".equals(name)) {
System.out.println("当前用户:" + value);
}
}
}
  • 修改:创建同名、同路径、同域名的 Cookie,设置新值并发送(覆盖旧值)。
  • 删除:创建同名、同路径、同域名的 Cookie,设置 setMaxAge(0) 并发送。
属性 作用描述
name Cookie 名称(创建后不可修改)
value Cookie 值(通常需编码,如 URL 编码处理特殊字符)
maxAge 有效期(秒):正数表示存活时间,0 表示立即删除,-1 表示会话级(浏览器关闭后删除)
path 适用路径:仅请求该路径及其子路径时携带(默认当前请求路径)
domain 适用域名:仅请求该域名时携带(默认当前域名,设置为 .example.com 可跨子域)
secure 仅在 HTTPS 连接中发送
httpOnly 禁止 JavaScript 访问(增强安全性)
  • 会话状态管理:如自动登录(记住用户名密码)、购物车临时存储。
  • 个性化设置:如用户主题偏好、语言设置。
  • 行为追踪:如记录浏览历史、广告推荐。

限制:单个 Cookie 大小通常不超过 4KB,同一域名下 Cookie 数量有限(一般 20-50 个)。

Session:服务器端的会话存储

Session 是服务器为每个客户端创建的内存对象,用于存储会话状态(如用户信息、权限等)。服务器通过SessionID(唯一标识)关联客户端,SessionID 通常通过 Cookie 或 URL 重写传递。

Session 工作原理

  1. 创建 Session:客户端首次请求时,服务器创建 Session 并生成 SessionID。
  2. 传递 SessionID:服务器通过 Set-Cookie: JSESSIONID=xxx 将 SessionID 发送给客户端(默认通过 Cookie)。
  3. 关联 Session:客户端后续请求通过 Cookie: JSESSIONID=xxx 携带 SessionID,服务器据此找到对应的 Session 对象。

Session 的操作方法

(1)创建或获取 Session
1
2
3
4
5
// 获取 Session:若不存在则创建(默认行为)
HttpSession session = request.getSession();

// 更明确的方式:true 表示不存在则创建,false 表示不存在则返回 null
HttpSession session = request.getSession(true);
(2)Session 数据操作
1
2
3
4
5
6
7
8
9
10
11
// 存储数据(键值对,值为任意对象)
session.setAttribute("user", new User("zhangsan", "admin"));

// 获取数据
User user = (User) session.getAttribute("user");

// 移除数据
session.removeAttribute("user");

// 获取所有属性名
Enumeration<String> attrNames = session.getAttributeNames();
(3)Session 生命周期管理
1
2
3
4
5
6
7
8
9
10
11
// 获取创建时间(毫秒时间戳)
long createTime = session.getCreationTime();

// 获取最后访问时间(毫秒时间戳)
long lastAccessTime = session.getLastAccessedTime();

// 设置超时时间(秒):超过该时间无请求则失效
session.setMaxInactiveInterval(1800); // 30 分钟

// 手动使 Session 失效(如退出登录)
session.invalidate();

全局超时配置:在 web.xml 中设置(单位:分钟),优先级低于 setMaxInactiveInterval

1
2
3
<session-config>
<session-timeout>30</session-timeout> <!-- 30 分钟 -->
</session-config>

SessionID 的传递方式

  • 默认方式(Cookie):SessionID 存储在会话级 Cookie 中(maxAge=-1),浏览器关闭后失效。

  • URL 重写:当浏览器禁用 Cookie 时,通过在 URL 后附加;jsessionid=xxx

    传递 SessionID:

1
2
3
4
// 对 URL 进行重写(自动添加 SessionID)
String url = response.encodeURL("/user/profile");
// 重定向时使用
String redirectUrl = response.encodeRedirectURL("/login");

Session 的持久化

Session 默认存储在服务器内存中,存在以下问题:

  • 服务器重启后 Session 丢失;
  • 内存占用随会话数增加而增长。

解决方案是Session 持久化,将 Session 存储到文件、数据库或缓存中:

  • StandardManager(Tomcat 默认):Web 应用关闭时,将内存中 Session 序列化到 SESSION.ser 文件(位于 work/Catalina/...),重启后恢复。
  • PersistentManager(Tomcat):更灵活,可配置定时将 Session 持久化到文件、数据库等(需实现 Store 接口)。
特性 Cookie Session
存储位置 客户端(浏览器本地文件 / 内存) 服务器端(内存 / 文件 / 数据库)
数据大小 单个通常 ≤ 4KB 无严格限制(取决于服务器配置)
安全性 较低(客户端可篡改) 较高(数据存储在服务器)
生命周期 可设置长期有效(maxAge 通常会话级(超时或服务器重启失效)
服务器负担 无(数据由客户端携带) 有(需存储和管理 Session 对象)
跨域支持 domain 属性限制 不支持跨域(SessionID 依赖域名)

最佳实践与选择建议

  1. Cookie 的使用建议
    • 存储非敏感数据(如用户偏好、主题设置);
    • 对敏感数据(如用户 ID)进行加密;
    • 启用 httpOnlysecure 属性增强安全性。
  2. Session 的使用建议
    • 存储敏感数据(如用户登录状态、权限);
    • 合理设置超时时间(避免过短影响体验,过长浪费资源);
    • 分布式系统中使用共享存储(如 Redis)管理 Session,避免单机依赖。
  3. 选择原则
    • 客户端可篡改的数据用 Session;
    • 轻量、非敏感且需长期保存的数据用 Cookie;
    • 结合使用:用 Cookie 存储 SessionID,Session 存储实际业务数据

欢迎关注我的其它发布渠道