JWT全解析:AI助手好用的认证方案,从入门到面试

小编 2 0

更新时间:2026年4月10日 | 本文是AI助手好用系列技术科普第一篇,后续将持续输出认证与授权方向的深度内容。

引言

JSON Web Token(简称JWT),是当前Web应用与微服务架构中最主流的无状态认证方案之一。无论是在前后端分离的SPA应用中,还是在分布式的微服务体系里,JWT几乎已经成为身份认证的标配。

然而很多学习者面临这样的困境:会用,但不懂原理;看过文档,但概念混淆;面试被问到,答不出层次。 本文将从痛点出发,逐步拆解JWT的诞生背景、核心结构、算法选择、代码实战、安全风险及面试考点,帮你建立完整的技术知识链路。

一、为什么需要JWT——Session认证的局限性

在JWT出现之前,Web应用最常用的认证方式是基于Session的认证。其工作流程如下:

  1. 用户登录,服务器验证凭证

  2. 服务器创建Session,将Session ID存入服务端存储(如内存、Redis)

  3. 服务器将Session ID通过Cookie返回给浏览器

  4. 后续请求浏览器自动携带Cookie,服务器根据Session ID查找到对应的会话信息完成认证

这套机制简单直观,但随着应用规模的扩大,问题逐渐暴露:

  • 水平扩展困难:用户登录后Session落在某台服务器上,其他服务器无法获取,需要引入Redis等集中存储实现Session共享,增加了系统复杂度和网络开销。

  • 服务端状态臃肿:每个在线用户都需要在服务端维护一份Session数据,百万级并发时内存消耗巨大。

  • 跨域支持受限:Cookie的跨域特性不友好,在微服务架构中多个服务可能部署在不同域名下,Session机制难以天然适配。

  • 即时注销困难:Session由服务端存储,可以立即删除实现注销,但这种“有状态”的设计与无状态的微服务理念背道而驰。

这些痛点催生了JWT的出现。JWT将用户身份信息直接编码在令牌中,服务端无需存储任何会话状态,实现了真正的无状态认证

二、核心概念讲解:JWT是什么

标准定义

JWT(JSON Web Token,RFC 7519)是一个开放标准,定义了一种紧凑且自包含的方式,用于在各方之间安全地传输JSON对象-4

拆解关键词:

  • 紧凑(Compact) :JWT以字符串形式存在,体积小,适合在URL、HTTP Header、POST参数中传输

  • 自包含(Self-contained) :JWT本身携带了所有必要的用户信息(如用户ID、角色、过期时间),服务端无需额外查询数据库

  • 安全传输:通过数字签名保证令牌的完整性和真实性,防止被篡改

生活化类比

可以把JWT想象成一张带防伪印章的通行证。你去游乐园买票时,工作人员给你一张盖了章的票(签发JWT),票面上写明了你的入场有效期、可游玩区域等信息。之后每进一个项目,工作人员只看票面的印章和内容就放行,不需要打电话问售票处确认你是否真的买过票。JWT的签名就是这个“印章”,确保没人能在票面上涂改内容后还能蒙混过关。

JWT的结构

一个完整的JWT由三个Base64Url编码的部分组成,中间用点号分隔:

text
复制
下载
<header>.<payload>.<signature>

1. Header(头部)

Header通常包含两个字段:令牌类型(typ)和签名算法(alg)。例如:

json
复制
下载
{
  "typ": "JWT",
  "alg": "HS256"
}

其中alg指定了签名所使用的加密算法,可以是HS256(对称加密)或RS256(非对称加密)等-1

2. Payload(载荷)

Payload是JWT的核心内容,包含了需要传递的声明(Claims) 。声明分为三类:

  • 注册声明:预定义的标准化字段,如iss(签发者)、exp(过期时间)、sub(主题/用户ID)、iat(签发时间)

  • 公共声明:可自定义的声明,但建议在IANA JSON Web Token Claims注册表中登记以避免冲突

  • 私有声明:双方约定自定义的信息

示例Payload:

json
复制
下载
{
  "sub": "1234567890",
  "name": "John Doe",
  "iat": 1516239022,
  "exp": 1516242622,
  "role": "admin"
}

重要提示:Payload仅经过Base64Url编码,并非加密。任何人都可以解码查看其内容,因此绝对禁止在Payload中存放密码、密钥等敏感信息-4-46

3. Signature(签名)

签名是JWT防篡改的基石。它的生成方式为:将编码后的Header和Payload用点号拼接,再使用Header中指定的算法和密钥进行签名-1

text
复制
下载
HMACSHA256(
  base64UrlEncode(header) + "." + base64UrlEncode(payload),
  secret
)

签名的核心作用是验证消息的真实性和完整性:服务端收到JWT后,使用同样的密钥重新计算签名,与JWT附带的签名比对,若一致则证明令牌未被篡改。

三、关联概念讲解:HS256 vs RS256

JWT的签名算法主要分为两类:对称加密算法(HS系列)非对称加密算法(RS系列)

HS256(对称加密)

HS256全称为HMAC with SHA-256,使用同一个密钥进行签名和验证-10

特点

  • 计算效率高,签名和验证速度快

  • 实现简单,只需一个共享密钥

  • 密钥必须在签名方和验证方之间共享

适用场景:集中式认证场景,即签名和验证都由同一可信方完成,例如单体应用内部的身份验证。

局限:任何拥有密钥的节点既能验证也能签发令牌。一旦密钥泄露,任意服务都可签发伪造的JWT。密钥轮换时需要重新部署所有依赖方-11-18

RS256(非对称加密)

RS256全称为RSA Signature with SHA-256,使用私钥签名、公钥验证的非对称加密方式-10

特点

  • 只有持有私钥的一方才能签发令牌,安全性更高

  • 任意持有公钥的第三方都可以验证令牌真伪,无需共享敏感密钥

  • 公钥可以通过JWKS(JSON Web Key Set)端点公开分发

  • 行业普遍推荐使用RS256-18

适用场景:微服务架构、第三方API授权、多服务共享认证等分布式环境。

示例:Auth0等身份认证平台在签发JWT时使用私钥签名,各微服务只需通过公开的JWKS端点获取公钥即可验证令牌,不需要知道私钥。

四、概念关系与区别总结

对比维度HS256(对称)RS256(非对称)
密钥数量1个(共享密钥)2个(私钥+公钥)
签名方与验证方必须相同/共享密钥签名用私钥,验证用公钥
密钥泄露风险高(密钥可被伪造令牌)低(公钥泄露不影响签名安全)
计算性能较慢(签名环节慢约两个数量级)
密钥轮换复杂度高(需重新部署所有依赖方)低(更换私钥,更新JWKS即可)
推荐程度适合集中式、内部系统推荐用于分布式、微服务架构

一句话概括:HS256是“一家人共用一把钥匙”,RS256是“一家之主用私章盖章,大家用公开图章验真”

五、代码示例:从签发到验证

以下使用Node.js的jsonwebtoken库,演示JWT的完整工作流程。

安装依赖

bash
复制
下载
npm install jsonwebtoken

签发Token(登录接口)

javascript
复制
下载
const jwt = require('jsonwebtoken');

const user = { id: 10001, username: 'alice', role: 'user' };
const SECRET = 'your-secret-key';  // 生产环境请使用环境变量

// 签发JWT,有效期1小时
const token = jwt.sign(
  { 
    sub: user.id,      // 用户标识
    username: user.username,
    role: user.role,
    iat: Math.floor(Date.now() / 1000)  // 签发时间
  },
  SECRET,
  { expiresIn: '1h' }
);
console.log(token);
// 输出: eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJzdWIiOjEwMDAxLCJ1c2VybmFtZSI6ImFsaWNlIiwicm9sZSI6InVzZXIiLCJpYXQiOjE3NDQyNzUyMDAsImV4cCI6MTc0NDI3ODgwMH0.xxx

验证Token(受保护接口)

javascript
复制
下载
app.get('/api/profile', (req, res) => {
  const authHeader = req.headers.authorization;
  if (!authHeader) {
    return res.status(401).json({ error: '未提供Token' });
  }

  // 标准格式:Bearer <token>
  const token = authHeader.split(' ')[1];
  
  try {
    const decoded = jwt.verify(token, SECRET);
    // 验证通过,返回用户信息
    res.json({ user: decoded });
  } catch (err) {
    if (err.name === 'TokenExpiredError') {
      res.status(401).json({ error: 'Token已过期' });
    } else {
      res.status(403).json({ error: 'Token无效' });
    }
  }
});

无状态刷新机制(Access Token + Refresh Token)

生产环境下,Access Token有效期通常设置为15分钟,配合长期有效的Refresh Token(7天)实现无感续签-39

javascript
复制
下载
function generateTokens(user) {
  // Access Token:短有效期,用于访问资源
  const accessToken = jwt.sign(
    { id: user.id, email: user.email },
    process.env.JWT_ACCESS_SECRET,
    { expiresIn: '15m' }
  );
  
  // Refresh Token:长有效期,仅用于换取新Access Token
  const refreshToken = jwt.sign(
    { id: user.id },
    process.env.JWT_REFRESH_SECRET,
    { expiresIn: '7d' }
  );
  
  return { accessToken, refreshToken };
}

刷新机制的核心设计原则:Refresh Token只能用于换取新的Access Token,不能直接作为资源访问凭证,以此缩短Token泄露的攻击窗口。

六、底层原理与技术支撑

JWT的安全性和功能性依赖于几个底层技术:

  • Base64Url编码:将JSON对象转换为URL安全的字符串,确保JWT可以在HTTP Header、URL参数等场景中无障碍传输。需要注意的是,编码≠加密,任何人都可以解码查看Payload内容。

  • 数字签名算法:包括HMAC系列(对称)和RSA/ECDSA系列(非对称)。签名机制确保了JWT的完整性——任何对Header或Payload的修改都会导致签名验证失败。

  • 声明(Claims)体系exp(过期时间)、nbf(生效时间)、iat(签发时间)、jti(唯一标识)等标准化字段,为令牌的生命周期管理和防重放提供了标准化基础。

正是这些底层技术的组合,赋予了JWT“无状态但可信”的核心特性。

七、安全攻击面与防护要点

1. alg: none 攻击

当服务端接受JWT Header中alg字段设置为none的令牌时,攻击者可绕过签名验证,任意篡改Payload内容,实现权限提升或用户身份伪造-55。2025年至2026年间,多个CVE漏洞(如CVE-2025-59934、CVE-2026-23993)均与此相关--

防护措施:服务端必须在验证流程中拒绝所有alg: none的令牌,并严格校验Header中的算法是否与系统预设的白名单一致-2

2. Token存储安全

将JWT存储在localStoragesessionStorage中是最常见的错误实践——这些存储机制可通过JavaScript直接访问,一旦存在XSS漏洞,攻击者可读取并窃取Token-24

最佳实践

  • Web端优先使用HttpOnly Cookie存储JWT,使JavaScript无法读取Token,从根本上杜绝XSS窃取-22

  • 若必须前端存储,建议采用BFF(Backend For Frontend)架构,将Token管理后置到服务端

  • 移动端使用平台安全存储API:iOS使用Keychain,Android使用Keystore-24

3. Token泄露风险

JWT作为Bearer Token,任何持有者均可使用。若Token在网络传输中被拦截,攻击者可冒充用户。

防护措施

  • 强制使用HTTPS,防止中间人攻击

  • 设置合理的exp过期时间,Access Token建议不超过15分钟,即使泄露也能将损害窗口缩至最小-18

  • 敏感场景可结合mTLS或DPoP(Demonstrating Proof-of-Possession)实现发送者约束

八、高频面试题与参考答案

面试题1:JWT由哪几部分组成?每部分的作用是什么?

参考答案:JWT由三部分组成,用点号分隔:Header(头部)、Payload(载荷)、Signature(签名)。

  • Header:包含令牌类型(typ)和签名算法(alg),如{"typ":"JWT","alg":"HS256"}

  • Payload:包含声明信息(claims),如用户ID、过期时间、角色等业务数据

  • Signature:通过对Header和Payload使用指定算法和密钥签名生成,用于验证令牌的真实性和完整性

踩分点:答出三部分名称、各自内容、签名的作用是防篡改和验证真实性。

面试题2:JWT和Session认证有什么区别?各有什么优缺点?

参考答案

维度Session认证JWT认证
服务端状态有状态,需要存储Session无状态,无需存储
扩展性需Session共享(Redis等)天生支持水平扩展
跨域支持依赖Cookie,跨域复杂通过Header携带,天然跨域
即时注销可立即删除Session实现需依赖黑名单或短过期时间
性能每次请求需查Session存储只需本地验证签名,无I/O开销

JWT适用于微服务架构、前后端分离、移动端等场景;Session适用于单体应用和对即时注销要求高的系统。

踩分点:对比维度完整,能结合场景说明各自适用条件。

面试题3:HS256和RS256有什么区别?如何选择?

参考答案:HS256是对称加密算法,使用同一密钥进行签名和验证;RS256是非对称加密算法,使用私钥签名、公钥验证。

选择建议:

  • HS256:适合集中式架构,签名方和验证方为同一可信服务,实现简单、性能高

  • RS256:推荐用于分布式架构和微服务,公钥可安全分发,私钥仅服务端持有,安全性更高,且密钥轮换更灵活

踩分点:区分对称/非对称,说清各自适用场景,明确RS256更推荐。

面试题4:JWT存在哪些安全风险?如何防范?

参考答案

  1. alg: none攻击:服务端必须拒绝alg: none的令牌,严格校验算法白名单

  2. Token存储风险:Web端使用HttpOnly Cookie替代localStorage,防止XSS窃取

  3. 传输拦截风险:强制使用HTTPS加密传输

  4. Token泄露滥用:设置短过期时间(如15分钟),配合Refresh Token机制减少泄露窗口

  5. Payload信息泄露:不存放敏感信息(密码、密钥),因为Payload仅编码不加密

踩分点:至少答出3种以上风险及对应防范措施,体现安全意识。

九、总结

本文围绕JWT的完整知识链路,梳理了以下核心要点:

  • 为什么需要JWT:Session机制在分布式场景下的扩展性瓶颈催生了无状态认证方案

  • JWT是什么:由Header、Payload、Signature三部分组成的紧凑型自包含令牌

  • 算法选择:HS256对称加密 vs RS256非对称加密,分布式场景推荐RS256

  • 代码实战:签发、验证、刷新Token的完整流程

  • 安全要点:拒绝alg: none、禁用localStorage存储、强制HTTPS、设置短过期时间

  • 面试考点:JWT结构、与Session对比、HS256/RS256差异、安全风险与防范

易错提醒:JWT的Payload仅经过Base64编码而非加密,禁止存放密码等敏感信息;Token存储切不可直接使用localStorage。

本文是AI助手好用系列的第一篇。下一篇将继续深入探讨OAuth 2.0协议与JWT的配合使用,以及生产环境中的Token黑名单与密钥轮换实践,欢迎持续关注。