前端鉴权机制

  在现代 Web 开发中,身份验证和会话管理是不可或缺的组成部分。HTTP是无状态的协议,为了在用户与服务器之间维持状态,前端和后端需要协同使用一些机制来标识用户身份并保障数据安全。本文将围绕 Cookie、Session、Token、JWT 四种常见方式进行介绍与对比,并结合实际说明 Cookie 在前端的基本操作方法。

Cookie:前端存储的基础工具

概念

Cookie 是由服务器发送到客户端并保存在浏览器中的一小段文本数据。它通常用于存储用户的会话信息、登录状态、偏好设置等。浏览器在每次请求该服务器时,都会自动携带相应域下的 Cookie,以便服务器识别用户的身份和状态。

属性

  • name/value:键值对形式存储数据,name 是 Cookie 的名称,value 是对应的值。
  • expires/max-age:设置 Cookie 的过期时间。expires 是一个固定的日期时间,当到达该时间时 Cookie 将失效。max-age 是一个相对时间,单位为秒,表示从设置 Cookie 时开始多少秒后 Cookie 失效。
  • path/domain:限制 Cookie 的作用路径和域名,指定该 Cookie 哪些路径和域名下的请求会带上该 Cookie。
  • secure:仅在 HTTPS 连接下传输该 Cookie,增强安全性,避免在不安全的 HTTP 协议下传输。
  • httpOnly:如果设置了 httpOnly 属性,Cookie 将不能通过 JavaScript 访问,避免被 XSS 攻击窃取。
  • sameSite:控制跨站请求中是否携带 Cookie。可设置为 Strict(严格模式,只有同源请求携带 Cookie)、Lax(宽松模式,部分跨站请求携带 Cookie)或 None(没有限制,所有请求携带 Cookie)。有效防范 CSRF 攻击。

操作方法

设置 Cookie

1
2
3
4
5
// 设置一个简单的 Cookie
document.cookie = "username=Tom; expires=Fri, 01 May 2025 12:00:00 UTC; path=/";

// 设置带有属性的 Cookie
document.cookie = "session_id=abc123; expires=Thu, 01 May 2025 12:00:00 UTC; path=/; secure; httpOnly; sameSite=Strict";

读取 Cookie

1
2
3
4
5
6
7
8
9
10
// 读取所有 Cookie
console.log(document.cookie); // 输出格式: "username=Tom; session_id=abc123"

// 获取特定 Cookie(通过正则匹配)
function getCookie(name) {
const match = document.cookie.match(new RegExp('(^| )' + name + '=([^;]+)'));
return match ? match[2] : null;
}

console.log(getCookie("username")); // "Tom"

删除 Cookie

1
2
// 通过设置过期时间为过去的日期删除 Cookie
document.cookie = "username=; expires=Thu, 01 Jan 1970 00:00:00 UTC; path=/";

注意:通过 document.cookie 只能操作非 httpOnly 的 Cookie。

Session:服务端管理的会话机制

概念

Session 是一种由服务器管理的会话机制,用于在用户与服务器之间保持会话状态。在用户登录后,服务器为每个用户创建一个 Session,并生成一个唯一的 Session ID,将其发送到客户端。客户端通常将这个 Session ID 存储在 Cookie 中,每次请求时,浏览器会自动将该 ID 发送到服务器,服务器通过该 ID 识别用户身份并恢复用户状态。

优点

  • 数据存储在服务端,安全性较高:由于用户数据存储在服务器端,不容易受到 XSS 等攻击的威胁,安全性相对较强。
  • 支持复杂的数据存储:Session 可以存储更多结构化的信息(如对象、数组等),而不像 Token 那样只能存储简单的字符串。

缺点

  • 服务器资源占用:每个用户会话需要在服务器端占用一定的内存或存储,随着用户数量的增加,服务器负担较重,扩展性较差。
  • 需要配合 Cookie 或 URL 传递 Session ID:如果 Cookie 被禁用,Session ID 需要通过 URL 传递,可能会暴露在 URL 中,存在一定的安全风险。

Token:无状态的身份令牌

概念

Token 是一种用于用户身份验证的字符串凭证,常用于前后端分离架构中。用户登录成功后,服务器会生成一个 Token 并返回给客户端,客户端在后续的请求中将该 Token 作为身份凭证,通过请求头或 URL 参数传回服务器,从而实现鉴权。Token 不依赖服务端存储用户状态,因此称为“无状态”认证机制。

优点

  • 无状态、可扩展:服务器无需记录每个用户的会话数据,天然适合分布式架构和微服务。
  • 跨平台支持:Token 通常使用字符串格式,前端、移动端、小程序等都易于集成。
  • 适合前后端分离:接口无状态化,前端可灵活控制请求。
  • 可加密处理:通过签名或加密机制提升安全性,防止伪造。

缺点

  • 安全性依赖客户端:Token 一般保存在本地存储(如 localStorage),容易受到 XSS 攻击。
  • 无法主动失效:服务端不记录状态,Token 一旦签发,除非设置过期时间,否则中途无法撤销。
  • 续期管理复杂:需要额外设计刷新机制(如 refresh token),以维持长期会话体验。

JWT:结构化的 Token 实现

概念

JWT(JSON Web Token)是一种开放标准(RFC 7519),用于在网络应用环境间传递声明(claims)。JWT 通常用于身份验证和信息交换,它由三部分组成:

  • Header:声明 Token 类型(通常是 JWT)和使用的签名算法(如 HMAC SHA256 或 RSA)。
  • Payload:存储需要传递的数据(如用户信息),该部分是明文可解码的。
  • Signature:由 Header 和 Payload 生成的加密签名,用于验证数据的完整性和防篡改。

优点

  • 自包含:JWT 将认证所需的所有信息包含在内,无需在服务端存储会话数据,便于分布式系统使用。
  • 无状态:JWT 不依赖服务端存储,适合大规模分布式系统和微服务架构。
  • 跨域支持:由于其无状态特性,JWT 易于跨域传输,非常适合前后端分离的项目。
  • 可加密和签名:JWT 可以使用密钥签名,防止数据篡改,也可以加密确保数据的机密性。

缺点

  • 明文数据暴露:Payload 部分是明文数据,虽然签名保证数据完整性,但敏感信息仍然暴露在 Token 内,使用时需谨慎。
  • Token 管理复杂:JWT 的无状态特性意味着服务端无法强制失效某个 Token,因此需要额外设计 Token 刷新机制或过期时间。
  • 过期管理:Token 的过期时间通常较短,但刷新机制的实现增加了系统复杂度。

场景

  • 前后端分离项目的用户认证:JWT 可在用户登录后返回给前端,前端每次请求时携带 Token 进行认证。
  • API 接口鉴权:用于保护接口资源,仅授权的用户可访问。
  • 单点登录(SSO):不同系统间共享认证信息,减少用户的多次登录操作。

区别分析

先是一张别,总结一下上面的四点。

特性 Cookie Session Token JWT
存储位置 客户端 服务端 客户端 客户端
安全性 较低(需配置) 较高 中等(加密可提高) 中等(加密可提高)
是否占用服务端资源 否 是 否 否
是否可跨域 否(需设置) 否 是 是
数据结构 键值对 可存对象 字符串 JSON结构
管理复杂性 简单 中等 中等 略复杂

存储方式

类型 存储位置 控制方
Cookie 浏览器自动保存(document.cookie) 服务端可设置(Set-Cookie)或客户端设置
Token(通常是JWT) 本地存储(localStorage、sessionStorage)或手动存入Cookie 前端开发者手动控制

发送方式

类型 是否自动携带 携带方式 控制方
Cookie ✅ 自动携带(只要是同源或设置了withCredentials) HTTP 请求头中的 Cookie 字段 浏览器自动或开发者设置
Token(JWT) ❌ 手动携带 通常放在 Authorization 头(如 Bearer xxx)或其他自定义头部 开发者手动设置请求头
  • JWT 是一种 Token 的格式,用来做身份验证(比如用户登录后返回的 token)。
  • 通常我们把 JWT 存在 localStorage 或 sessionStorage 中,并在每次请求时 手动带上。
  • ❗也可以把 JWT 存在 Cookie 里,这样就可以配合浏览器自动发送,但要小心 CSRF 风险。

传统 Web 登录是 Session + Cookie 组合:

  • 服务端创建 Session,分配一个唯一 ID(session_id),并通过 Set-Cookie 写入浏览器。
  • 浏览器之后的请求会自动携带这个 Cookie,服务端用这个 ID 找回 Session。
作者

Fu9Zhou

发布于

2025-04-12

许可协议