cookie和session
一、Cookie 是什么?
-
定义:
Cookie 是服务器发送到客户端浏览器并存储在本地的一小段数据,用于跟踪用户会话或存储用户偏好等信息。浏览器每次向服务器发送请求时,会携带同一域名下的 Cookie。 -
工作原理:
- 客户端首次请求服务器,服务器生成 Cookie(如用户 ID、登录状态等),通过响应头
Set-Cookie
发送给浏览器。 - 浏览器将 Cookie 存储在本地,并在后续同域名请求中,通过请求头
Cookie
自动携带发送给服务器。 - 服务器解析 Cookie,识别用户状态。
- 客户端首次请求服务器,服务器生成 Cookie(如用户 ID、登录状态等),通过响应头
-
特点:
- 存储位置:客户端(浏览器)。
- 存储容量:单个 Cookie 通常不超过 4KB,每个域名最多存储约 20-50 个 Cookie(不同浏览器限制不同)。
- 有效期:可设置过期时间(持久化 Cookie),若不设置则为会话级 Cookie(浏览器关闭后删除)。
- 安全性:数据明文存储(可被篡改),需通过
HttpOnly
(防 XSS)、Secure
(仅 HTTPS 传输)等属性增强安全。 - 跨域:默认仅同域名有效,不支持跨域。
二、Session 是什么?
-
定义:
Session 是服务器端用于存储用户会话数据的机制,每个用户有独立的 Session 标识(如JSESSIONID
),通常通过 Cookie 或 URL 重写传递给客户端。 -
工作原理:
- 客户端首次请求服务器,服务器创建 Session 对象(存储用户信息,如登录状态、购物车等),生成唯一
Session ID
。 - 服务器通过响应头
Set-Cookie: JSESSIONID=xxx
将Session ID
存储到客户端 Cookie 中(或通过 URL 携带)。 - 后续请求中,浏览器携带
JSESSIONID
,服务器根据该 ID 查找对应的 Session 数据。
- 客户端首次请求服务器,服务器创建 Session 对象(存储用户信息,如登录状态、购物车等),生成唯一
-
特点:
- 存储位置:服务器端(内存、数据库或缓存)。
- 存储容量:无固定限制,可存储大量数据。
- 有效期:默认与浏览器会话绑定(关闭浏览器后过期),也可设置超时时间(如 30 分钟未操作则失效)。
- 安全性:数据存储在服务器端,相对安全,但依赖 Cookie 传递
Session ID
,若 Cookie 被窃取,Session 可能被劫持(需配合HttpOnly
、Secure
等)。 - 跨域:默认不跨域,需通过共享
Session ID
或分布式 Session 方案实现。
三、核心区别对比
特性 | Cookie | Session |
---|---|---|
存储位置 | 客户端(浏览器) | 服务器端 |
数据安全性 | 较低(明文存储,易被篡改) | 较高(数据在服务器,需防范 Session 劫持) |
存储容量 | 小(4KB 以内) | 大(无固定限制) |
有效期 | 可持久化(设置过期时间)或会话级 | 会话级(默认)或设置超时时间 |
对服务器压力 | 无(存储在客户端) | 有(占用服务器内存 / 存储) |
跨域支持 | 同域名有效 | 需额外处理(如共享 Session 机制) |
典型应用 | 记住登录状态、用户偏好、购物车标识 | 登录验证、用户会话数据(如权限、购物车详情) |
四、应用场景
-
Cookie 的常见场景:
- 记住用户登录状态(设置持久化 Cookie,如
remember-me
)。 - 存储用户偏好(如主题设置、语言选择)。
- 跟踪用户行为(如广告投放、统计分析)。
- 记住用户登录状态(设置持久化 Cookie,如
-
Session 的常见场景:
- 登录验证(存储用户登录状态、权限信息)。
- 临时数据存储(如购物车中的商品列表、表单临时填写内容)。
- 分布式系统中,通过 Redis/Memcached 实现 Session 共享(解决集群环境下的 Session 同步问题)。
五、实战示例(用户登录场景)
-
登录时的 Cookie 使用:
- 登录成功后,服务器返回用户 ID 存储在 Cookie 中(如
user_id=123
),并设置HttpOnly
和Secure
属性防止攻击。 - 客户端后续请求自动携带
user_id
,服务器通过该 ID 快速识别用户。
- 登录成功后,服务器返回用户 ID 存储在 Cookie 中(如
-
登录时的 Session 使用:
- 服务器创建 Session 对象,存储用户完整信息(用户名、权限、登录时间等),生成
JSESSIONID
并通过 Cookie 传递给客户端。 - 服务器通过
JSESSIONID
查找 Session 数据,验证用户权限(如示例中判断user.id==1
跳转管理员页面)。
- 服务器创建 Session 对象,存储用户完整信息(用户名、权限、登录时间等),生成
六、总结
-
选择建议:
- 存储少量、非敏感数据(如标识、偏好)→ 使用 Cookie。
- 存储敏感或大量数据(如登录状态、用户详情)→ 使用 Session(或结合 Token 机制,如 JWT)。
- 分布式系统中,优先使用 Token(如 JWT) 替代传统 Session(避免服务器间 Session 同步问题)。
-
注意事项:
- Cookie 需加密敏感数据(如
user_id
可加密后存储)。 - Session 需设置合理超时时间,避免内存泄漏。
- 生产环境中,Cookie 和 Session 均需配合 HTTPS 使用,防止数据被中间人窃取。
- Cookie 需加密敏感数据(如
六、如何在Java中设置和获取Cookie?
在 Java 中,可以使用 javax.servlet.http.Cookie
类来设置和获取 Cookie。
设置 Cookie
设置 Cookie 一般在 Servlet 中进行,步骤如下:
- 创建
Cookie
对象,指定 Cookie 的名称和值。 - 可以设置 Cookie 的其他属性,如过期时间、路径、域名等。
- 将
Cookie
对象添加到HttpServletResponse
中。
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("/setCookie")
public class SetCookieServlet extends HttpServlet {@Overrideprotected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {// 创建一个名为 "user_id" 的 Cookie,值为 "123"Cookie userIdCookie = new Cookie("user_id", "123");// 设置 Cookie 的过期时间为 3600 秒(1 小时)userIdCookie.setMaxAge(3600);// 设置 Cookie 的路径为根路径,这样整个应用都可以访问该 CookieuserIdCookie.setPath("/");// 设置 Cookie 为 HttpOnly,防止 JavaScript 脚本访问userIdCookie.setHttpOnly(true);// 设置 Cookie 仅通过 HTTPS 传输userIdCookie.setSecure(true);// 将 Cookie 添加到响应中response.addCookie(userIdCookie);response.getWriter().println("Cookie 已设置");}
}
-
设置 Cookie:
Cookie
类的构造函数接受两个参数:Cookie 的名称和值。setMaxAge
方法用于设置 Cookie 的过期时间,以秒为单位。如果设置为负数,表示该 Cookie 是会话级 Cookie,浏览器关闭时会被删除;如果设置为 0,则会立即删除该 Cookie。setPath
方法用于设置 Cookie 的路径,指定哪些路径下的页面可以访问该 Cookie。setHttpOnly
方法用于设置 Cookie 是否为 HttpOnly,设置为true
可以防止 JavaScript 脚本访问该 Cookie,增强安全性。setSecure
方法用于设置 Cookie 是否仅通过 HTTPS 传输,设置为true
可以防止 Cookie 在 HTTP 连接中被窃取。response.addCookie
方法将Cookie
对象添加到响应中,发送给客户端。
获取 Cookie
获取 Cookie 同样在 Servlet 中进行,步骤如下:
- 从
HttpServletRequest
中获取所有的 Cookie。 - 遍历这些 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("/getCookie")
public class GetCookieServlet extends HttpServlet {@Overrideprotected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {// 从请求中获取所有的 CookieCookie[] cookies = request.getCookies();if (cookies != null) {for (Cookie cookie : cookies) {if ("user_id".equals(cookie.getName())) {String userId = cookie.getValue();response.getWriter().println("获取到的 user_id Cookie 值为: " + userId);return;}}}response.getWriter().println("未找到 user_id Cookie");}
}
-
获取 Cookie:
request.getCookies
方法用于从请求中获取所有的 Cookie,返回一个Cookie
数组。- 遍历该数组,通过
getName
方法获取 Cookie 的名称,与需要的名称进行比较,找到对应的 Cookie 后,通过getValue
方法获取其值。