Skip to content

什么是 JWT?它的三段结构分别是什么? ​

  • 标签:Spring Security、认证授权、后端

🏛 业务架构师 ​

JWT(JSON Web Token)是无状态的令牌格式:服务器签发后自己保存状态无需查库(或仅需验签),客户端每次请求带上即可完成认证。

三段结构(以点号分隔 header.payload.signature):

  1. Header:声明令牌类型与签名算法 {"alg": "HS256", "typ": "JWT"}——Base64Url 编码;
  2. Payload: Claims(声明集)——标准字段(sub 用户标识、exp 过期时间、iat 签发时间、iss 签发方、aud 受众)+ 业务自定义字段(用户 ID、角色、租户)。注意 Payload 只是 Base64 编码不是加密——不能放敏感信息(密码、身份证),任何人可解码查看;
  3. Signature:对前两段用服务端密钥签名(HS256 对称密钥 / RS256 非对称)——这是防篡改的核心:改一个字符签名即失效。

验证流程:服务端收到 JWT → 用密钥验签(确认没被篡改)→ 校验 exp 等声明 → 信任 Payload 里的身份。"信任建立在签名上而不是加密上"——JWT 保证完整性,不保证机密性。

业务视角的取舍:JWT 的价值是无状态验证——网关/服务本地验签即可认证,不查会话库,横向扩容与跨服务认证极其顺畅(微服务标配);代价是签发后无法主动作废(注销、改权限立即生效是难题,见优缺点题的解法)。我的架构习惯:短时效 Access Token + Refresh Token 组合,把"不可控窗口"压到分钟级——业务上即享受无状态的红利,又把风险框在可接受范围。

🏗 系统架构师 ​

JWT(JSON Web Token)= 三段式自包含令牌:Header.Payload.Signature,三段各自 Base64Url 编码以 . 连接。

  • Header:{"alg": "HS256", "typ": "JWT"}——声明签名算法与类型(alg 是安全敏感字段——见 alg=none 攻击);
  • Payload(Claims):标准声明(iss 签发者、exp 过期、sub 主体、aud 受众、iat/nbf 时间、jti 唯一 ID)+ 自定义声明(userId、roles、tenantId)。注意:Payload 只是 Base64 编码不是加密——勿放敏感信息(密码、身份证),任何拿到令牌的人都能解码看到;
  • Signature:HMACSHA256(base64(header) + "." + base64(payload), secret)(或 RSA/ECDSA 私钥签名)——签名保证完整性:内容被篡改则验签失败;但不提供机密性(JWE 才加密)。

机制本质(架构视角):JWT 把"会话状态"从服务端搬到客户端——服务端无状态、验签即认证:签名算法只有密钥持有者能产出,因此 Payload 里的身份声明可信(在 exp 内、未被篡改)。这带来天然的多服务共享:任何持有公钥/密钥的服务都能本地验签,不需要共享会话存储或集中认证调用——这是微服务/分布式系统偏爱它的根本原因。

代价(下一题展开):无法主动作废(签出去就有效到 exp)、令牌体积(携带 claims)、密钥管理(HS256 的共享密钥分发 vs RS256 的公私钥体系)。

安全要点:始终用成熟库验签(锁死期望算法,防 alg none/算法混淆攻击);exp 必设且服务端强制校验(时钟偏移留 30~60s leeway);敏感信息不进 payload。

💻 全栈开发专家 ​

JWT(JSON Web Token):自包含的、签名保护的令牌——身份信息编码在 token 里,服务端无需存储会话即可验证(无状态认证的基石)。

三段结构(点号分隔:header.payload.signature,均为 Base64Url):

  1. Header:算法与类型 {"alg":"RS256","typ":"JWT"}(kid 标识多密钥);
  2. Payload:声明集——
    • 注册声明:sub(主体/用户ID)、exp(过期时间戳)、iat(签发时间)、nbf、iss(签发者)、aud(受众)、jti(唯一 ID,做黑名单/幂等用);
    • 公共/私有声明:业务字段 {"roles":["ADMIN"],"tenant":"acme"};
    • 注意:payload 只是编码不是加密,别放密码/身份证等敏感信息(Base64 一解就见);
  3. Signature:对前两段用 header 指定算法签名——RS256( header.payload, 私钥 ),防篡改的核心。

验签流程:服务端用公钥/密钥重算签名比对 + 校验 exp/iss/aud——任何一段被改,签名对不上。

Java 实战(jjwt 或 Spring Security OAuth2 Resource Server):

java
// 签发
String jwt = Jwts.builder()
    .subject("u1001").claim("roles", List.of("ADMIN"))
    .issuedAt(new Date()).expiration(Date.from(now.plus(30, MINUTES)))
    .signWith(privateKey).compact();

// 资源服务器一行接入
http.oauth2ResourceServer(o -> o.jwt(j -> j
    .decoder(OAuth2AuthorizationServerConfiguration...)));

算法坑:禁用 none 算法校验(历史漏洞)、固定算法白名单防 算法混淆攻击(把 RS256 token 改 HS256 用公钥当 HMAC 密钥——验签时必须锁死预期算法);密钥用非对称(RS256/ES256)适合多服务(认证中心持私钥,各服务持公钥验证)。