JWT 资源服务器默认校验了什么、没校验什么?roles 声明为什么 hasRole 不认?时钟偏差有多大容忍?密钥轮换的时候旧令牌会怎么样?这篇在 Spring Boot 4.0.8、Spring Security 7 上自己签令牌、自己起 JWKS 服务逐项实测。
不带令牌 GET /read → HTTP 401,WWW-Authenticate: Bearer resource_metadata="http… 有效令牌 GET /read → HTTP 200,/read 用户=alice authorities=[FactorGrantedAuthority [authority=FACTOR_BEARER, issuedAt=2026-10-20T04:23:34.529572Z], SCOPE_read, SCOPE_write] 有效令牌 GET /admin(令牌里有 roles = [ADMIN]) → HTTP 403,WWW-Authenticate: Bearer error="insufficient_sco… error=insufficient_scope description=The request requires higher privileges than provided by the access token. 没有 scope 的令牌 GET /read → HTTP 403,WWW-Authenticate: Bearer error="insufficient_sco… error=insufficient_scope description=The request requires higher privileges than provided by the access token. 篡改了 payload(sub 改成 mallory)的令牌 GET /read → HTTP 401,WWW-Authenticate: Bearer error="invalid_token", … error=invalid_token description=An error occurred while attempting to decode the Jwt: Signed JWT rejected: Invalid signature alg = none 的令牌 GET /read → HTTP 401,WWW-Authenticate: Bearer error="invalid_token", … error=invalid_token description=Unsupported algorithm of none alg = HS256、用公钥字节当密钥的令牌 GET /read → HTTP 401,WWW-Authenticate: Bearer error="invalid_token", … error=invalid_token description=An error occurred while attempting to decode the Jwt: Signed JWT rejected: Another algorithm expected, or no matching key(s) found 过期 90 秒的令牌 GET /read → HTTP 401,WWW-Authenticate: Bearer error="invalid_token", … error=invalid_token description=An error occurred while attempting to decode the Jwt: Jwt expired at 2026-10-20T04:22:02Z nbf 在 120 秒之后的令牌 GET /read → HTTP 401,WWW-Authenticate: Bearer error="invalid_token", … error=invalid_token description=An error occurred while attempting to decode the Jwt: Jwt used before 2026-10-20T04:25:32Z iss 是别的签发者的令牌 GET /read → HTTP 200,/read 用户=alice authorities=[FactorGrantedAuthority [authority=FACTOR_BEARER, issuedAt=2026-10-20T04:23:34.561582Z], SCOPE_read, SCOPE_write]
签名与算法被严格检查;时间有 60 秒容忍;签发者默认不校验;scope 映射成 SCOPE_,roles 被忽略。
过期 30 秒的令牌(默认) → HTTP 200,/read 用户=alice authorities=[FactorGrantedAuthority [authority=FACTOR_BEARER, issuedAt=2026-10-20T04:23:35.954695Z], SCOPE_read, SCOPE_write] 过期 90 秒的令牌(默认) → HTTP 401,WWW-Authenticate: Bearer error="invalid_token", … error=invalid_token description=An error occurred while attempting to decode the Jwt: Jwt expired at 2026-10-20T04:22:02Z 过期 30 秒的令牌,JwtTimestampValidator(Duration.ZERO) → HTTP 401,WWW-Authenticate: Bearer error="invalid_token", … error=invalid_token description=An error occurred while attempting to decode the Jwt: Jwt expired at 2026-10-20T04:23:02Z iss 不对的令牌,JwtValidators.createDefaultWithIssuer → HTTP 401,WWW-Authenticate: Bearer error="invalid_token", … error=invalid_token description=An error occurred while attempting to decode the Jwt: The iss claim is not valid iss 正确的令牌,createDefaultWithIssuer → HTTP 200,/read 用户=alice authorities=[FactorGrantedAuthority [authority=FACTOR_BEARER, issuedAt=2026-10-20T04:23:38.927857Z], SCOPE_read, SCOPE_write]
JwtTimestampValidator 可调容忍;createDefaultWithIssuer 校验 iss。
第 1 步 JWKS = {k1}:k1 令牌 → HTTP 200,/read 用户=alice authorities=[FactorGrantedAuthority [authority=FACTOR_BEARER, issuedAt=2026-10-20T04:23:40.356155Z], SCOPE_read, SCOPE_write]
此时 JWKS 服务被访问了 1 次
第 2 步 JWKS 切成 {k2} 之后立刻:k2 令牌(kid 不在缓存里) → HTTP 200,/read 用户=alice authorities=[FactorGrantedAuthority [authority=FACTOR_BEARER, issuedAt=2026-10-20T04:23:40.374228Z], SCOPE_read, SCOPE_write]
这一步 JWKS 服务又被访问了 1 次
第 3 步:k1 令牌(k2 令牌触发的那次刷新已经把缓存换成了 {k2}) → HTTP 401,WWW-Authenticate: Bearer error="invalid_token", … error=invalid_token description=An error occurred while attempting to decode the Jwt: Signed JWT rejected: Another algorithm expected, or no matching key(s) found
第 4 步 等 16 秒之后:k2 令牌 → HTTP 200,/read 用户=alice authorities=[FactorGrantedAuthority [authority=FACTOR_BEARER, issuedAt=2026-10-20T04:23:56.390336Z], SCOPE_read, SCOPE_write]
第 5 步:k1 令牌(JWKS 里已经没有 k1) → HTTP 401,WWW-Authenticate: Bearer error="invalid_token", … error=invalid_token description=An error occurred while attempting to decode the Jwt: Signed JWT rejected: Another algorithm expected, or no matching key(s) found
累计 JWKS 服务被访问 4 次
第 6 步 JWKS 服务宕机:k2 令牌(已缓存) → HTTP 200,/read 用户=alice authorities=[FactorGrantedAuthority [authority=FACTOR_BEARER, issuedAt=2026-10-20T04:23:56.398411Z], SCOPE_read, SCOPE_write]
JWKS 服务宕机时刚启动的应用:k2 令牌 → HTTP 401,WWW-Authenticate: Bearer resource_metadata="http…kid 不在缓存时立即重新获取;旧 key 立刻失效;JWKS 宕机时已缓存的 key 可用。
GET /read(令牌 scope = "read write") → HTTP 200,/read 用户=alice authorities=[FactorGrantedAuthority [authority=FACTOR_BEARER, issuedAt=2026-10-20T04:23:59.248369Z], SCOPE_read, SCOPE_write] GET /anything → HTTP 200,/anything 用户=alice authorities=[FactorGrantedAuthority [authority=FACTOR_BEARER, issuedAt=2026-10-20T04:23:59.266118Z], SCOPE_read, SCOPE_write]
scope 映射成 SCOPE_xxx;roles 要自己写转换器。