使用SymmetricSecurityKey签名JWT如何指定kid?多源JWT校验问题
问题2:多来源JWT校验(兼容无kid的HmacSha256令牌)
你现在用kid == null来区分Hmac令牌的思路是可行的,但要考虑后续扩展性,避免以后加新密钥时逻辑混乱。这里给你几个优化建议和代码示例:
情况1:只有一个Hmac密钥来源
如果目前只有一个Hmac发行方,直接在kid == null分支返回对应的对称密钥就行,建议额外加iss判断,防止意外无kid的令牌被错误校验:
var validationParams = new TokenValidationParameters { ValidateIssuer = true, ValidIssuers = new[] { "rsa-issuer", "hmac-issuer" }, ValidateAudience = true, ValidAudience = "common-audience", ValidAlgorithms = new[] { SecurityAlgorithms.RsaSha256, SecurityAlgorithms.HmacSha256 }, IssuerSigningKeyResolver = (token, securityToken, kid, param) => { var jwt = securityToken as JwtSecurityToken; if (jwt == null) return null; // 带kid的用RSA密钥匹配 if (!string.IsNullOrEmpty(kid)) { return new List<SecurityKey> { GetRsaCertificateByKid(kid).PublicKey }; } // 无kid且是指定Hmac发行者的令牌,用对应密钥校验 else if (jwt.Issuer == "hmac-issuer") { return new List<SecurityKey> { new SymmetricSecurityKey(Encoding.UTF8.GetBytes("hmac-secret")) }; } return null; } };
情况2:多个Hmac密钥来源
如果以后会有多个Hmac发行方,只靠kid == null就不够了,必须结合iss(发行者)字段来区分不同的密钥:
IssuerSigningKeyResolver = (token, securityToken, kid, param) => { var jwt = securityToken as JwtSecurityToken; if (jwt == null) return null; // 处理RSA令牌(带kid) if (!string.IsNullOrEmpty(kid)) { return new List<SecurityKey> { GetRsaKeyByKid(kid) }; } // 处理无kid的Hmac令牌,按发行者匹配对应密钥 else { return jwt.Issuer switch { "hmac-payments-service" => new List<SecurityKey> { new SymmetricSecurityKey(Encoding.UTF8.GetBytes("payments-hmac-secret")) }, "hmac-user-service" => new List<SecurityKey> { new SymmetricSecurityKey(Encoding.UTF8.GetBytes("users-hmac-secret")) }, _ => null // 未知发行者,返回null会触发校验失败 }; } }
额外注意点
- 一定要设置
ValidAlgorithms字段,限制允许的签名算法,防止恶意用其他算法的令牌绕过校验。 - 如果以后Hmac发行方也开始加kid了,你只需要在Resolver里新增kid到对应Hmac密钥的映射,完全不用改现有逻辑,兼容性很强。
内容的提问来源于stack exchange,提问作者user9510058
相关产品推荐
相关产品推荐

