深入理解 Cookie 与 Session —— Web 状态保持详解与实战

HTTP 协议是**无状态(Stateless)**的,这意味着:

  • 每次请求之间,服务器不会主动记住你是谁。

  • 用户在一次请求中登录了,下一次请求服务器依然当你是新访客。

  • 像购物车、个人中心、支付流程等功能无法在多次请求之间共享状态。

所以,状态保持技术的核心目标是:

让服务器在多个 HTTP 请求中"记住"客户端的身份和相关信息。

最常见的两种技术就是 Cookie 和 Session。


二、Cookie ------ 浏览器端的状态记录

1. 概念

Cookie 是一小段存储在浏览器端 的文本数据,由服务器生成并通过响应头 Set-Cookie 发送给浏览器保存。之后浏览器访问同一域名时会自动携带 Cookie 发送给服务器。

2. 工作原理

  1. 首次请求:浏览器访问服务器,服务器在响应头中设置 Cookie。

  2. 存储:浏览器将 Cookie 保存到本地文件(每个浏览器保存方式不同)。

  3. 后续请求:浏览器在请求头中自动带上 Cookie 信息。

  4. 服务器读取:服务器解析 Cookie,从而识别用户身份。

流程图示意:

css 复制代码
[浏览器] --请求--> [服务器] 
[服务器] --Set-Cookie--> [浏览器保存] 
[浏览器] --携带Cookie请求--> [服务器读取并识别]

3. 示例

html 复制代码
HTTP/1.1 200 OK
Set-Cookie: username=zhangsan; Path=/; HttpOnly; Max-Age=3600

下次请求:

html 复制代码
GET /index.html HTTP/1.1
Cookie: username=zhangsan
属性 作用
Name=Value 键值对数据
Domain 指定 Cookie 生效的域名
Path 指定 Cookie 生效的路径
Expires / Max-Age 设置过期时间
HttpOnly 防止 JavaScript 读取,增强安全性
Secure 仅在 HTTPS 下传输

优点:

  • 浏览器自动管理,无需额外代码处理传输。

  • 可以持久化存储(设置过期时间)。

缺点:

  • 存储容量小(单个约 4KB)。

  • 安全性差(数据明文存储在客户端,易被窃取或篡改)。

  • 每次请求都会携带 Cookie,会增加流量消耗。


三、Session ------ 服务器端的状态记录

1. 概念

Session 是一种服务器端存储 的会话数据机制。

当用户第一次访问时,服务器会为其创建一个 Session,并分配一个唯一的 Session ID,将这个 ID 返回给浏览器保存(通常通过 Cookie)。

2. 工作原理

  1. 首次访问:服务器生成 Session 数据(例如登录状态、购物车内容),并生成唯一的 Session ID。

  2. 返回 Session ID :服务器通过 Cookie 将 Session ID 发给浏览器(如 JSESSIONID=xyz123)。

  3. 浏览器保存:浏览器保存 Session ID 到 Cookie。

  4. 后续请求:浏览器在请求中携带 Session ID,服务器根据该 ID 找到对应的 Session 数据。

3. 示例

html 复制代码
Set-Cookie: JSESSIONID=xyz123; Path=/; HttpOnly

后续请求:

html 复制代码
GET /cart HTTP/1.1
Cookie: JSESSIONID=xyz123

4. Session 特性

  • 存储位置:服务器内存 / 数据库 / 分布式缓存(如 Redis)。

  • 生命周期:默认 30 分钟(可配置)。

  • 容量限制:取决于服务器内存,理论上可存储较大数据。

  • 安全性:数据不直接暴露给客户端,安全性高。


四、Cookie 与 Session 的关系

实际上,Session 通常依赖 Cookie 来保存 Session ID:

  • Cookie 中只保存一个 Session ID。

  • 具体的用户数据(登录状态、购物车等)存放在服务器的 Session 对象中。

这种方式结合了两者的优点:

  • 减少 Cookie 存储压力。

  • 提升安全性(敏感数据不放在客户端)。


五、Cookie 与 Session 的对比

对比项 Cookie Session
存储位置 客户端(浏览器) 服务器端
安全性 易被窃取或篡改(需加密) 高,数据不暴露给客户端
存储容量 单个 ≤ 4KB 受服务器内存限制
生命周期 可设置过期时间 默认短时存储,可配置
性能影响 占用客户端空间,增加网络流量 占用服务器内存
使用场景 保存非敏感、需要持久化的数据 保存敏感数据(如登录信息)

六、实际开发中的应用

1. 用户登录流程(Session 版)

  1. 用户输入账号密码并提交。

  2. 服务器验证成功后,创建 Session,保存用户信息。

  3. 将 Session ID 写入 Cookie。

  4. 后续请求带上 Session ID,服务器即可识别用户。

2. 用户登录流程(Cookie 版)

  1. 用户输入账号密码并提交。

  2. 服务器验证成功后,将用户信息加密后写入 Cookie。

  3. 后续请求直接解析 Cookie 获取用户信息(需注意安全风险)。


七、安全性问题与防护措施

Cookie 和 Session 都是状态保持机制,但如果使用不当,可能被攻击者利用。常见问题包括:

原理 :攻击者获取了你的 Cookie(尤其是 Session ID),就能冒充你的身份。
场景 :公共 WiFi 抓包、XSS 注入读取 Cookie。
防护措施:

  • 使用 HTTPS 传输,防止中间人截获。

  • 设置 HttpOnly,防止 JS 脚本读取 Cookie。

  • 设置 Secure,仅允许在 HTTPS 下传输。

原理 :攻击者在客户端或通过响应头写入相同名称的 Cookie,从而覆盖原有 Cookie 内容,导致身份被冒用或数据被篡改。
场景:

  • 同一域名下的不同子域篡改 Cookie。

  • 恶意响应头设置同名 Cookie 覆盖原值。
    防护措施:

  • 为 Cookie 设置明确的 Domain 和 Path 限制作用范围。

  • 对 Cookie 值进行签名和验证,防止篡改。

3. Session 固定攻击(Session Fixation / Session 重定义)

原理 :攻击者提前获取或制造一个合法的 Session ID,然后诱导受害者使用该 Session ID。一旦受害者登录,攻击者就能使用相同的 Session ID 登录到受害者的账号。
流程示例:

  1. 攻击者访问网站,获取一个合法的 Session ID=abc123。

  2. 攻击者将该 Session ID 发送给受害者(通过 URL、恶意链接等方式)。

  3. 受害者在该 Session ID 下登录。

  4. 攻击者用相同的 Session ID 就能直接登录受害者账号。

防护措施:

  • 登录成功后重新生成 Session ID(关键)。

  • 不允许通过 URL 传递 Session ID。

  • 对 Session 设置较短的过期时间,并限制 IP/UA 绑定。

4. Session 过期处理不当

原理 :Session 过期后,如果前端没有提示重新登录,可能导致用户操作失败,体验差。
防护措施:

  • 后端返回特定状态码(如 401/440)。

  • 前端检测到状态码后跳转到登录页,并可选保存用户输入内容。


在 Java Web(Servlet)开发中,Cookie 和 Session 是内置支持的,我们可以很方便地使用它们。

java 复制代码
import jakarta.servlet.*;
import jakarta.servlet.http.*;
import java.io.IOException;

public class SetCookieServlet extends HttpServlet {
    @Override
    protected void doGet(HttpServletRequest request, HttpServletResponse response) throws IOException {
        // 创建 Cookie 对象
        Cookie cookie = new Cookie("username", "zhangsan");
        // 设置 Cookie 过期时间(秒),这里设置 1 小时
        cookie.setMaxAge(60 * 60);
        // 设置作用路径(默认是当前项目路径)
        cookie.setPath("/");
        // 添加到响应
        response.addCookie(cookie);
        response.getWriter().write("Cookie 已设置!");
    }
}
java 复制代码
public class GetCookieServlet extends HttpServlet {
    @Override
    protected void doGet(HttpServletRequest request, HttpServletResponse response) throws IOException {
        Cookie[] cookies = request.getCookies();
        if (cookies != null) {
            for (Cookie c : cookies) {
                if ("username".equals(c.getName())) {
                    response.getWriter().write("读取到 Cookie:username=" + c.getValue());
                }
            }
        } else {
            response.getWriter().write("没有找到 Cookie");
        }
    }
}

2. Session 的使用

2.1 创建与存储 Session 数据
java 复制代码
public class SetSessionServlet extends HttpServlet {
    @Override
    protected void doGet(HttpServletRequest request, HttpServletResponse response) throws IOException {
        // 获取 Session,没有则创建
        HttpSession session = request.getSession();
        // 存储数据到 Session
        session.setAttribute("user", "zhangsan");
        // 设置 Session 过期时间(秒)
        session.setMaxInactiveInterval(30 * 60);
        response.getWriter().write("Session 已存储!");
    }
}
2.2 获取 Session 数据
java 复制代码
public class GetSessionServlet extends HttpServlet {
    @Override
    protected void doGet(HttpServletRequest request, HttpServletResponse response) throws IOException {
        HttpSession session = request.getSession(false); // false 表示没有就不创建
        if (session != null) {
            String user = (String) session.getAttribute("user");
            if (user != null) {
                response.getWriter().write("Session 中的 user = " + user);
            } else {
                response.getWriter().write("Session 中没有 user 数据");
            }
        } else {
            response.getWriter().write("Session 不存在");
        }
    }
}

3. 小技巧与注意事项

  • Session 默认使用 Cookie 存 Session ID(JSESSIONID),如果禁用 Cookie,可以通过 URL 重写:
java 复制代码
response.encodeURL("myServlet");
  • Session 清除:
java 复制代码
session.invalidate();
  • Cookie 安全性:对于敏感信息,应加密后再存储,或者仅存 Session ID。

  • Session 分布式存储:在分布式环境中使用 Redis 等中间件来存储 Session,实现会话共享。


九、总结

  1. Cookie 适合存放少量非敏感数据,可跨会话持久化。

  2. Session 安全性高,适合保存登录等敏感信息。

  3. 最佳实践:用 Cookie 存 Session ID,核心数据放 Session。

  4. Java Web 开发 内置了 Cookie 和 Session API,用法简单高效。

  5. 在安全上,需防范 Cookie 重定义 、Session 固定攻击 、Cookie 劫持 等问题。

相关推荐
能源革命14 小时前
Vue 网格拖拽布局组件全景指南:7 大方案深度对比
前端·javascript·vue.js
PC2005_cloud14 小时前
AI 汉字漂移实录:它为什么总把「学习」写成日语「学習」
前端·后端
穆梓兰煊14 小时前
AI供应链安全不再只是包安全,还涉及模型与数据
前端·数据库
RaaS10014 小时前
AI网关能做Prompt注入防护吗?AI网关核心功能详解
前端·后端
deli00715 小时前
Skill 怎么写才被 Agent 命中?18 条规则做成 SKILL.md 校验器,规范样例 92 分
前端
Hum8le15 小时前
CTF题目《easy_web》(安洵杯 2019 变种 Web)
前端·安全·web安全
coding漫漫长路15 小时前
二值化后还剩1212个黑点,OCR却认成了乱码
前端
不可能片场15 小时前
AI视频口型对齐 用音频驱动说话镜头
前端·electron
Lank_M15 小时前
OCR一个字没认错,倾斜2.5°却把行序排乱了
前端
daols8815 小时前
vue 表格组件 vxe-table 实现自定义多行编辑功能
前端·javascript·vue.js·vxe-table