Asp.net Core 6 MVC RSA算法身份验证未授权问题求助
RSA签名JWT授权失败排查及修复
核心问题1:发行方(Issuer)验证不匹配
生成Token时,SecurityTokenDescriptor的Issuer设为空字符串,但验证配置中开启了ValidateIssuer = true且未指定ValidIssuer,导致验证逻辑判定Token无效。
修复方案:
- 方式一:统一Issuer值,生成和验证时保持一致
生成Token时设置有效Issuer:
验证配置中同步设置:var descriptor = new Microsoft.IdentityModel.Tokens.SecurityTokenDescriptor { Issuer = "your-issuer-name", // 例如"IndraUI" Claims = payload, SigningCredentials = new SigningCredentials(new RsaSecurityKey(rsa), SecurityAlgorithms.RsaSha256) { CryptoProviderFactory = new CryptoProviderFactory { CacheSignatureProviders = false } }, IssuedAt = System.DateTime.UtcNow, Expires = System.DateTime.UtcNow.AddDays(15), };options.TokenValidationParameters = new TokenValidationParameters { ValidIssuer = "your-issuer-name", // 其他配置... }; - 方式二:若不需要验证Issuer,关闭验证开关
options.TokenValidationParameters = new TokenValidationParameters { ValidateIssuer = false, // 其他配置... };
核心问题2:受众(Audience)验证未配置但开启
生成Token时未指定Audience,但验证配置中ValidateAudience = true且未设置ValidAudience,同样会触发验证失败。
修复方案:
- 方式一:配置Audience并保持一致
生成Token时添加Audience:
验证配置中同步设置:var descriptor = new Microsoft.IdentityModel.Tokens.SecurityTokenDescriptor { Audience = "your-audience-name", // 例如"IndraAPI" // 其他配置... };options.TokenValidationParameters = new TokenValidationParameters { ValidAudience = "your-audience-name", // 其他配置... }; - 方式二:关闭Audience验证(若业务不需要)
options.TokenValidationParameters = new TokenValidationParameters { ValidateAudience = false, // 其他配置... };
问题3:公钥加载逻辑冗余且易出错
手动替换公钥的头尾标记和换行可能因格式问题(比如换行符不一致)导致公钥加载失败,建议使用RSA.ImportFromPem简化加载逻辑:
修复后的公钥加载代码:
builder.Services.AddSingleton<RsaSecurityKey>(provider => { string publicKey = System.IO.File.ReadAllText("D:\\wwwroot\\keys\\publickey.crt"); var rsa = System.Security.Cryptography.RSA.Create(); rsa.ImportFromPem(publicKey.AsSpan()); // 直接加载PEM格式公钥,无需手动处理Base64 return new RsaSecurityKey(rsa); });
问题4:服务实例获取方式不当
在AddJwtBearer中直接调用builder.Services.BuildServiceProvider()会创建新的服务提供者实例,可能导致和后续注入的服务不一致,建议通过options.Events获取服务:
修复后的验证配置代码:
builder.Services.AddAuthentication(JwtBearerDefaults.AuthenticationScheme) .AddJwtBearer(options => { options.IncludeErrorDetails = true; options.TokenValidationParameters = new TokenValidationParameters { RequireSignedTokens = true, RequireExpirationTime = true, ValidateLifetime = true, ValidateAudience = false, // 先关闭测试,确认签名有效后再开启 ValidateIssuer = false, // 先关闭测试,确认签名有效后再开启 }; // 通过请求上下文获取正确的RSA密钥实例 options.Events = new JwtBearerEvents { OnTokenValidated = context => { var rsaKey = context.HttpContext.RequestServices.GetRequiredService<RsaSecurityKey>(); context.SecurityTokenValidatedContext.TokenValidationParameters.IssuerSigningKey = rsaKey; return Task.CompletedTask; } }; });
排查建议
先关闭Issuer和Audience验证,测试Token是否能正常通过签名验证,确认签名逻辑没问题后,再逐步开启需要的验证项,缩小排查范围。
内容的提问来源于stack exchange,提问作者Pravin
相关产品推荐
相关产品推荐

