Cookie学习记录
是服务器通过 HTTP 响应头发送给浏览器、由浏览器保存在本地的小型文本数据(通常小于 4KB)。
后续浏览器向同一服务器发送请求时,会通过 HTTP 请求头自动携带匹配的 Cookie,让服务器识别这是之前来过的客户端,从而实现状态保持。
Cookie 主要用于解决 HTTP 协议 “无状态” 的问题(HTTP 协议本身不会记录请求间的关联,Cookie 就是用来 “记住” 信息的桥梁)
Cookie 的空间小,无法存储大容量数据,如果需要存储大量数据,可以使用 localStorage;
防 CSRF 令牌:服务器下发 csrfToken=abc123 的 Cookie(带 HttpOnly),前端提交表单时需从 Cookie 中读取该令牌并放在请求体中,服务器验证令牌一致性,防止跨站请求伪造。
Cookie 的交互完全基于 HTTP 协议,无需前端主动干预:
- 客户端发起首次请求:例如用户第一次访问一个 url,此时请求头中没有服务器下发的 Cookie
- 服务器收到客户端的第一次请求后,若需要记住客户端,会在 HTTP 响应头中添加 Set-Cookie 字段,将 Cookie 数据传给浏览器
示例:Set-Cookie: userId=123; Path=/; Max-Age=3600这个 Cookie,有效期 1 小时 - 浏览器解析 Set-Cookie 头,按规则将 Cookie 存储到本地
- 当客户再次访问相同的 url 时,浏览器会自动检查本地存储的 Cookie,若 Cookie 的数据与当前请求匹配,那么就会在 HTTP 请求头中添加 Cookie 字段,将数据传给服务器。
- Name=Value:Cookie 的核心数据,是服务器实际需要的信息
- Expires:Cookie 的过期事件,过期后浏览器会自动删除 Cookie,若不设置,关闭浏览器就会删除
- Max-Age:Cookie 的有效时长,优先级高于 Expires。若设置为 0 或负数,浏览器会立马删除。
- Path:限制 Cookie 的作用路径,只有当请求路径匹配或包含该 Path 时,浏览器才会携带 Cookie。默认为 “当前请求路径”。
- Domain:限制 Cookie 的作用域名:只有当请求的域名匹配该 Domain 时,浏览器才会携带 Cookie。默认为 “当前请求的域名”
- Secure:安全属性,仅当请求时 HTTPS 协议时,浏览器才会携带 Cookie。
- HttpOnly:防止脚本攻击,设置后,前端无法通过 js 访问该 Cookie,只能由浏览器自动携带,可有效防止 XSS 攻击窃取 Cookie
- SameSite:跨域安全属性,限制 Cookie 在跨域请求中是否携带,防止 CSRF 攻击
- 会话 Cookie:没有设置 Expires 或 Max-Age 属性,仅在浏览器会话期间有效,浏览器关闭后,Cookie 自动删除;临时状态保持,比如临时购物车、未登录用户的会话标识
- 持久 Cookie:设置了 Expires 或 Max-Age 属性,有效期有属性值决定,长期状态保持,比如登录后 7 天内无需重新登录,就是通过持久 Cookie 实现的
- 第三方 Cookie:Cookie 的 “Domain” 属性与当前访问的域名不一致,通常来自广告、统计工具等第三方服务
应用场景
- 用户登录状态维持:服务器验证账号密码正确后,下发 token=xxx(带 HttpOnly/Secure)的 Cookie,后续请求携带该 Cookie,服务器验证后确认用户已登录。
- 购物车数据存储:未登录用户的购物车数据,可通过会话 Cookie 临时存储(关闭浏览器丢失);登录用户的购物车可通过持久 Cookie 关联到账号。
- 用户偏好设置:比如记住用户的 “主题颜色”“语言选择”,服务器下发 theme=dark 的持久 Cookie,下次访问时自动加载偏好。
- 防 CSRF 令牌:服务器下发 csrfToken=abc123 的 Cookie(带 HttpOnly),前端提交表单时需从 Cookie 中读取该令牌并放在请求体中,服务器验证令牌一致性,防止跨站请求伪造。
前端操作:前端只能操作 未设置 HttpOnly 属性 的 Cookie,核心通过 document.cookie API 实现
- 读取 Cookie:document.cookie
- 设置 Cookie:document.cookie = “key=value;
- 删除 Cookie:Cookie 没有直接的 “删除” API,需通过 设置 Max-Age=0 或 Expires=过去时间,让浏览器自动删除
后端操作(Spring Boot):
设置 Cookie:通过 HttpServletResponse.addCookie() 方法设置 Cookie:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31import javax.servlet.http.Cookie;
import javax.servlet.http.HttpServletResponse;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RestController;
@RestController
public class LoginController {
// 登录接口:下发登录态 Cookie
@PostMapping("/login")
public Result login(String username, String password, HttpServletResponse response) {
// 假设验证账号密码成功
if ("admin".equals(username) && "123456".equals(password)) {
Cookie loginTokenCookie = new Cookie("loginToken", "eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9...");
// 设置 Cookie 属性
loginTokenCookie.setPath("/"); // 整个应用生效
loginTokenCookie.setMaxAge(7 * 24 * 3600); // 有效期 7 天(单位:秒)
loginTokenCookie.setHttpOnly(true); // 前端无法 JS 访问
loginTokenCookie.setSecure(false); // 开发环境暂不启用(生产环境设为 true,仅 HTTPS)
loginTokenCookie.setSameSite("Lax"); // 防 CSRF
// 下发 Cookie 到前端
response.addCookie(loginTokenCookie);
return Result.success("登录成功");
} else {
return Result.fail("账号密码错误");
}
}
}
本博客所有文章除特别声明外,均采用 CC BY-NC-SA 4.0 许可协议。转载请注明来源 Myskill-blog!