Cookie、Session 与 Token

Cookie 是浏览器按域名和路径管理的小型键值数据。服务端通过 Set-Cookie 写入,符合条件时浏览器在后续请求中自动携带 Cookie 请求头。

常见属性:

  • Expires / Max-Age:有效期。
  • Domain / Path:发送范围。
  • Secure:仅通过 HTTPS 发送。
  • HttpOnly:禁止 JavaScript 读取,降低 Token 被 XSS 窃取的风险。
  • SameSite:限制跨站请求携带 Cookie。

SameSite=None 必须同时设置 Secure

Session

传统 Session 流程:

  1. 用户登录成功,服务端创建 Session。
  2. 浏览器保存只包含 Session ID 的 Cookie。
  3. 后续请求自动携带 Session ID。
  4. 服务端查询 Session 得到用户状态。

优点是服务端可以主动吊销;缺点是集群环境需要共享 Session、粘性会话或集中存储。

Token 与 JWT

Token 通常由前端显式放入 Authorization: Bearer ...。JWT 是一种 Token 格式,不等于完整认证方案。

JWT 的 payload 默认只是 Base64URL 编码,不是加密,不能存放密码等敏感信息。签名用于校验完整性和签发者,并不会隐藏内容。

  • JavaScript 无法读取,降低凭证被 XSS 直接窃取的风险。
  • 浏览器自动携带,需要正确设置 SameSite 并考虑 CSRF。

localStorage

  • 不会自动随请求发送,CSRF 风险模型不同。
  • 任意成功执行的同源 XSS 都能读取并外传 Token。

不存在脱离场景的绝对答案。高价值 Web 会话通常优先考虑 Secure + HttpOnly + SameSite Cookie,并同时做好 XSS、CSRF 和服务端鉴权。

Access Token 与 Refresh Token

  • Access Token:有效期短,用于业务接口。
  • Refresh Token:有效期更长,只用于换取新的 Access Token,权限和暴露面应更小。

多个请求同时发现 Token 过期时,应使用“单飞锁”:只允许一个刷新请求执行,其他请求等待同一个 Promise,避免刷新风暴。

刷新失败后要清理本地身份并跳转登录,不能无限重试。

高频追问

  • 删除 Cookie 为什么必须匹配 Domain 和 Path?
  • HttpOnly 能否防止 XSS 发起恶意请求?
  • JWT 如何注销?
  • 跨子域登录如何设计?
  • 为什么前端路由守卫不能代替服务端鉴权?