Nimbus 用两层结构覆盖 JWS、JWE、JWK 和 JWT:底层对象(SignedJWT、ECDSASigner、MACVerifier),以及把密钥选择、签名检查和声明检查串联起来的 DefaultJWTProcessor。Spring Security 的资源服务器就构建在它之上,因此它的默认设置也就是大多数 Spring API 实际执行的规则。
使用处理器时,JWSVerificationKeySelector 就是允许列表:配置为 ES256 后,它拒绝了 RS256 令牌,也拒绝了以 EC 密钥的 PEM 文本为密钥的 HS256 令牌,报错 Another algorithm expected, or no matching key(s) found;不配置任何选择器时,处理器会拒绝所有令牌。未签名的令牌会被拒绝(Unsecured (plain) JWTs are rejected, extend class to handle)。底层 API 没有这种保护——用 PEM 文本构建的 MACVerifier 让那个伪造的 HS256 令牌验证通过了——因此,根据令牌头部来选择验证器的代码,会重现经典的算法混淆缺陷。应像示例那样使用处理器。
DefaultJWTClaimsVerifier 默认允许 60 秒的时钟偏差,而且除非列为必需声明,否则 exp 是可选的——示例要求 sub 和 exp,并锁定了颁发者。ES256 会拒绝 P-384 密钥(The ES256 algorithm is not allowed or supported by the JWS signer),DER 编码的签名则只是验证失败;可以用 JWT 调试器检查签名长度。
10.10 版对 HS、RS、PS、ES 系列以及 EdDSA 和较新的 Ed25519 名称完成了往返测试。Ed25519 需要 classpath 中有 Google Tink:缺少它时,签名报错 NoClassDefFoundError: com/google/crypto/tink/subtle/Ed25519Sign$KeyPair。ES256K 需要支持 secp256k1 的提供程序,例如 Bouncy Castle,因为 JDK 中没有这样的提供程序。