github.com/golang-jwt/jwt/v5 使用标准库中的密钥解析、校验和签名 JWT:HMAC 用 []byte,以及 *rsa.PublicKey、*ecdsa.PublicKey 和 ed25519.PublicKey。5.3.1 版对 HS、RS、PS、ES 系列和 EdDSA 的签名与验证均成功;ES256K 以及完全指定的 Ed25519 和 Ed448 算法名称都没有注册对应的签名方法。
验证的关键在于传给 jwt.Parse 的 keyfunc。每种签名方法都会检查收到的密钥的 Go 类型,因此当 keyfunc 返回 *ecdsa.PublicKey 时,RS256 令牌报错 RSA verify expects *rsa.PublicKey,以 PEM 文本为密钥的 HS256 令牌报错 HMAC verify expects []byte。如果 keyfunc 对每个令牌都返回原始字节,这层防护就不复存在——在检查中,把 PEM 文件加载为 []byte 的 keyfunc 让那个伪造的 HS256 令牌验证通过了。应像示例那样,用 jwt.WithValidMethods 传入确切的算法,并让 keyfunc 返回有类型的密钥。
只有当 keyfunc 返回哨兵值 jwt.UnsafeAllowNoneSignatureType 时,alg: none 才能验证通过;返回任何真实密钥都会得到 'none' signature type is not allowed。ES256 在签名时拒绝 P-384 密钥,只给出简单的 key is invalid。ES256 签名是 JWS 要求的 64 字节原始 r‖s;DER 签名会报错 crypto/ecdsa: verification error,可以借助 JWT 调试器和 DER ⇄ 原始格式转换器排查。
v5 默认开启声明校验,但 exp 是可选的——不含它的令牌永远有效——而且没有容差。jwt.WithExpirationRequired()、jwt.WithIssuer、jwt.WithAudience 和 jwt.WithLeeway 可以补上这些缺口;错误可以用 errors.Is(err, jwt.ErrTokenExpired) 匹配,而不必比较字符串。
要验证身份提供商签发的令牌,可将它与 JWKS 客户端搭配使用,并用 JWKS 检测查看提供商发布的内容;需要处理 JWE 或 JWK 时,可以改用 go-jose。