.NET 6升.NET 8后仅密钥验证的JWT认证失败求助
问题原因
.NET 8配套的Microsoft.IdentityModel.Tokens库调整了JWT签名验证逻辑:当配置单个IssuerSigningKey时,默认会强制校验令牌header中的kid(密钥ID)字段,要求其与密钥的KeyId匹配。你的令牌header没有kid,且密钥未设置KeyId,因此触发IDX10517错误,导致认证失败。
解决方案
提供两种可行方案,根据你的令牌是否可修改选择:
方案1:添加kid匹配(适合可更新令牌的场景)
给认证密钥设置KeyId,同时更新JWT令牌的header添加对应的kid字段。
修改认证配置代码
services.AddAuthentication(options => { options.DefaultAuthenticateScheme = JwtBearerDefaults.AuthenticationScheme; options.DefaultChallengeScheme = JwtBearerDefaults.AuthenticationScheme; options.DefaultScheme = JwtBearerDefaults.AuthenticationScheme; }).AddJwtBearer("external", options => { options.TokenValidationParameters = new TokenValidationParameters { RequireExpirationTime = false, ValidateLifetime = false, ValidateIssuer = false, ValidateAudience = false, ValidateIssuerSigningKey = true, // 给密钥设置KeyId IssuerSigningKey = new SymmetricSecurityKey(Encoding.ASCII.GetBytes(customKey)) { KeyId = "internal-server-key" // 自定义唯一标识 }, }; });
更新JWT令牌header
{ "alg": "HS256", "kid": "internal-server-key" // 与密钥的KeyId一致 }
方案2:忽略kid验证(适合无法更新现有令牌的场景)
如果内部服务器使用的固定令牌无法修改,可通过以下两种方式跳过kid校验:
方法A:设置KidValidator委托
直接指定KidValidator为总是返回true的委托,绕过kid验证:
services.AddAuthentication(options => { options.DefaultAuthenticateScheme = JwtBearerDefaults.AuthenticationScheme; options.DefaultChallengeScheme = JwtBearerDefaults.AuthenticationScheme; options.DefaultScheme = JwtBearerDefaults.AuthenticationScheme; }).AddJwtBearer("external", options => { options.TokenValidationParameters = new TokenValidationParameters { RequireExpirationTime = false, ValidateLifetime = false, ValidateIssuer = false, ValidateAudience = false, ValidateIssuerSigningKey = true, IssuerSigningKey = new SymmetricSecurityKey(Encoding.ASCII.GetBytes(customKey)), // 忽略kid验证 KidValidator = (tokenKid, securityKey, validationParameters) => true }; });
方法B:使用密钥集合代替单个密钥
将单个密钥放入IssuerSigningKeys集合中,验证器会尝试所有密钥,不再强制校验kid:
services.AddAuthentication(options => { options.DefaultAuthenticateScheme = JwtBearerDefaults.AuthenticationScheme; options.DefaultChallengeScheme = JwtBearerDefaults.AuthenticationScheme; options.DefaultScheme = JwtBearerDefaults.AuthenticationScheme; }).AddJwtBearer("external", options => { options.TokenValidationParameters = new TokenValidationParameters { RequireExpirationTime = false, ValidateLifetime = false, ValidateIssuer = false, ValidateAudience = false, ValidateIssuerSigningKey = true, // 使用IssuerSigningKeys集合代替单个IssuerSigningKey IssuerSigningKeys = new List<SecurityKey> { new SymmetricSecurityKey(Encoding.ASCII.GetBytes(customKey)) }, }; });
内容的提问来源于stack exchange,提问作者iritN
相关产品推荐
相关产品推荐

