杰瑞科技汇

Java Web Cookie 如何设置与获取?

什么是 Cookie?

Cookie 是一种在客户端(浏览器)存储小块数据(通常为 4KB 左右)的技术,它由服务器生成,发送给浏览器,浏览器会将其保存起来,之后,浏览器每次向同一服务器发起请求时,都会自动携带这些 Cookie。

Java Web Cookie 如何设置与获取?-图1
(图片来源网络,侵删)

可以把 Cookie 想象成服务器发给客户端的“会员卡”或“身份证”,客户端每次访问服务器时,都自动出示这张“卡”,服务器通过识别这张“卡”来辨认用户,或者记住用户的一些设置。


Cookie 的工作流程

Cookie 的工作流程非常简单,基于 HTTP 协议的无状态特性来增加状态:

  1. 客户端首次请求:浏览器访问一个网站(www.example.com/login)。
  2. 服务器响应:服务器验证用户名和密码成功后,会创建一个 Cookie 对象(JSESSIONID=xxxxxx),并通过 Set-Cookie 响应头发送给浏览器。
  3. 浏览器存储:浏览器接收到这个响应头后,会解析 Set-Cookie 并将 Cookie 存储在本地。
  4. 后续请求:浏览器再次向 www.example.com 的任何资源(如 /home, /profile)发起请求时,会自动在请求头中带上 Cookie 头,格式为 Cookie: JSESSIONID=xxxxxx
  5. 服务器识别:服务器从请求头中读取 Cookie,从而识别出是哪个用户,并可以据此提供个性化的服务(如显示用户名、保持登录状态等)。

在 Java Web 中如何操作 Cookie?

在 Java Web 中,我们主要通过 Servlet API 来操作 Cookie,下面我们分步讲解。

创建和发送 Cookie(服务器 -> 客户端)

在 Servlet 中,通过 response 对象来创建并发送 Cookie。

Java Web Cookie 如何设置与获取?-图2
(图片来源网络,侵删)
import javax.servlet.ServletException;
import javax.servlet.annotation.WebServlet;
import javax.servlet.http.Cookie;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;
@WebServlet("/createCookie")
public class CreateCookieServlet extends HttpServlet {
    @Override
    protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
        // 1. 创建一个 Cookie 对象
        // 参数1: Cookie 的名称 (name)
        // 参数2: Cookie 的值 (value)
        Cookie usernameCookie = new Cookie("username", "john_doe");
        // 2. (可选) 设置 Cookie 的属性
        // 设置 Cookie 的有效期,单位为秒,如果设置为0,则删除Cookie。
        // 如果不设置,Cookie 会在浏览器关闭后失效(会话 Cookie)。
        usernameCookie.setMaxAge(60 * 60 * 24); // 有效期为1天
        // 设置 Cookie 的路径,只有访问该路径及其子路径时,浏览器才会携带此 Cookie。
        // 设置为 "/myapp",则只有访问 /myapp/xxx 时才会携带。
        // 如果不设置,默认是当前 Servlet 的路径。
        usernameCookie.setPath("/");
        // 3. 将 Cookie 添加到响应对象中
        // 这一步会向客户端发送 "Set-Cookie" 响应头
        resp.addCookie(usernameCookie);
        // 4. 给用户一个反馈
        resp.getWriter().write("Cookie 'username' has been created for you!");
    }
}

读取 Cookie(客户端 -> 服务器)

在 Servlet 中,通过 request 对象来读取客户端发送过来的所有 Cookie。

import javax.servlet.ServletException;
import javax.servlet.annotation.WebServlet;
import javax.servlet.http.Cookie;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;
@WebServlet("/readCookie")
public class ReadCookieServlet extends HttpServlet {
    @Override
    protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
        // 1. 从 request 对象中获取所有 Cookie
        Cookie[] cookies = req.getCookies();
        // 2. 检查是否存在 Cookie
        if (cookies != null) {
            for (Cookie cookie : cookies) {
                // 3. 获取 Cookie 的名称和值
                String name = cookie.getName();
                String value = cookie.getValue();
                // 我们只查找名为 "username" 的 Cookie
                if ("username".equals(name)) {
                    resp.getWriter().write("Welcome back, " + value + "!");
                    return; // 找到后直接返回
                }
            }
        }
        // 如果没有找到任何 Cookie 或目标 Cookie
        resp.getWriter().write("No 'username' cookie found. Please log in first.");
    }
}

删除 Cookie

删除 Cookie 并没有一个专门的 removeCookie() 方法,它的原理是:创建一个同名、同路径、有效期(maxAge)为 0 的 Cookie,并发送给客户端,浏览器会覆盖掉旧的 Cookie,并因为其已过期而立即删除它。

import javax.servlet.ServletException;
import javax.servlet.annotation.WebServlet;
import javax.servlet.http.Cookie;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;
@WebServlet("/deleteCookie")
public class DeleteCookieServlet extends HttpServlet {
    @Override
    protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
        // 1. 创建一个与要删除的 Cookie 同名的 Cookie 对象
        Cookie usernameCookie = new Cookie("username", "");
        // 2. 设置有效期为 0,这是关键!
        // 这会告诉浏览器:“这个 Cookie 已经过期了,请立即删除它。”
        usernameCookie.setMaxAge(0);
        // 3. 设置路径,必须与创建时设置的路径完全一致,才能成功删除
        usernameCookie.setPath("/");
        // 4. 将 Cookie 添加到响应中
        resp.addCookie(usernameCookie);
        resp.getWriter().write("Cookie 'username' has been deleted.");
    }
}

Cookie 的常用属性

属性 方法 描述
Name new Cookie(name, value) Cookie 的唯一标识符,创建后不可修改。
Value new Cookie(name, value) Cookie 的值,注意:不能包含空格、逗号、分号等特殊字符。
Max-Age setMaxAge(int seconds) Cookie 的生命周期(秒),如果为正数,表示在指定的秒数后过期;如果为 0,则立即删除;如果为负数(默认值),表示是“会话 Cookie”,浏览器关闭即失效。
Path setPath(String uri) 指定 Cookie 的有效路径,只有请求的 URL 匹配该路径或其子路径时,浏览器才会携带此 Cookie。/app 会匹配 /app/user/app/order
Domain setDomain(String pattern) 指定 Cookie 的有效域名,设置为 .example.com,则 www.example.comstore.example.com 都可以访问此 Cookie,默认为当前服务器的域名。
Secure setSecure(boolean flag) 如果为 true,则只有通过 HTTPS(加密)协议连接时,才会将 Cookie 发送到服务器,用于保护敏感数据。
HttpOnly setHttpOnly(boolean flag) 如果为 true,则禁止 JavaScript 通过 document.cookie 访问此 Cookie,这是防止 XSS(跨站脚本攻击)窃取 Cookie的重要手段。

Cookie 的优缺点与安全考量

优点

  1. 简单易用:API 简单,在所有浏览器中都得到支持。
  2. 状态保持:能够很好地弥补 HTTP 协议无状态的缺陷。
  3. 服务器端压力小:数据存储在客户端,不占用服务器资源。

缺点

  1. 存储容量小:单个 Cookie 通常限制在 4KB 左右,一个域名下最多约 20 个。
  2. 安全性较低
    • 明文传输:默认情况下,Cookie 是明文传输的,容易被窃取,应尽量配合 HTTPS 使用。
    • XSS 攻击:Cookie 没有设置 HttpOnly,恶意脚本可以读取并窃取用户的 Cookie。
    • CSRF 攻击:攻击者可以诱骗用户在已登录的网站上执行一个恶意请求,浏览器会自动带上用户的 Cookie,从而冒充用户执行操作。
  3. 性能开销:每次 HTTP 请求都会携带所有相关的 Cookie,增加了网络请求的大小。
  4. 用户隐私:用户可以在浏览器设置中禁用 Cookie,导致功能失效。

安全最佳实践

  1. 标记为 HttpOnly:对于任何用于认证的 Session ID 或敏感信息,必须设置 HttpOnlytrue
    cookie.setHttpOnly(true);
  2. 使用 Secure 属性:对于任何敏感的 Cookie,应设置 Securetrue,确保其只在 HTTPS 连接下传输。
    cookie.setSecure(true); // 注意:这要求你的应用运行在 HTTPS 下
  3. 不要存储敏感信息:绝对不要在 Cookie 中存储密码、信用卡号等高度敏感的信息,Cookie 应该只存储不敏感的标识符(如 Session ID)或用户偏好设置。
  4. 设置合理的 PathMax-Age:遵循最小权限原则,将 Path 设置得尽可能具体,避免不必要的 Cookie 被发送,为非会话 Cookie 设置合理的 Max-Age

Cookie vs. Session

在 Java Web 开发中,Cookie 和 Session 是两个紧密相关但又截然不同的概念。

特性 Cookie Session
存储位置 客户端(浏览器) 服务器端
少量文本数据(如 JSESSIONID=xxx 任意类型和数量的 Java 对象(通过 setAttribute 设置)
安全性 较低,易被窃取和篡改 较高,数据在服务器端,客户端只持有 ID
生命周期 可通过 setMaxAge 设置,可长期存在 通常与用户会话绑定,会话超时则失效
依赖性 不依赖 Session 通常依赖 Cookie(通过 Cookie 传递 Session ID)

Java Web Cookie 如何设置与获取?-图3
(图片来源网络,侵删)
  • Session 是服务器用来保存用户状态的“保险箱”。
  • Cookie 是发给用户,让用户每次访问时都能找到“保险箱钥匙”(即 Session ID)的“钥匙扣”。

当用户禁用 Cookie 时,Session 机制可能会失效(除非使用 URL 重写等其他技术),这体现了 Cookie 在 Session 管理中的基础性作用。

Cookie 是 Java Web 开发中一项基础且重要的技术,它简单、高效,用于实现用户认证、个性化设置等功能,由于其固有的安全风险,在使用时必须格外小心,始终遵循安全最佳实践,特别是为敏感 Cookie 设置 HttpOnlySecure 属性,在现代 Web 开发中,虽然有 LocalStorage、SessionStorage 等客户端存储方案,但 Cookie 在处理会话管理(Session)和跨域认证等方面仍然扮演着不可替代的角色。

分享:
扫描分享到社交APP
上一篇
下一篇