我意识到有许多与升级到 .NET 8 有关的问题,并且我已尽最大努力查看我面临的问题是否相关,但我见过的解决方案都不适合我,而且我还没有没有注意到其他人也面临同样的问题。
不幸的是,我对 JWT 和身份验证相当无知,但让我解释一下我观察到的情况。
适用于 .NET 7 的代码如下所示:
options.TokenValidationParameters = new TokenValidationParameters
{
ValidateIssuer = true,
ValidateIssuerSigningKey = true,
ValidateAudience = true,
ValidateLifetime = true,
ClockSkew = TimeSpan.Zero
};
options.Authority = KeyCloakOptions.Authority;
options.MetadataAddress = $"{options.Authority}/.well-known/openid-configuration";
options.RequireHttpsMetadata = false;
options.RefreshOnIssuerKeyNotFound = true;
options.Audience = KeycloakOptions.AudienceInvoice;
options.Events = new JwtBearerEvents
{
OnAuthenticationFailed = context =>
{
_logger.LogDebug("Authentication failed: " + context);
return Task.CompletedTask;
},
OnTokenValidated = context =>
{
_logger.LogDebug("JWT Bearer Token Validated.");
return Task.CompletedTask;
}
};
如果我使用此代码,我将收到有关发行人的错误,例如:
IDX10204:无法验证发行人。 validationParameters.ValidIssuer 为 null 或空格且validationParameters.ValidIssuers 为 null 或空。
这可以通过修改
TokenValidationParameters
以包含发行人来解决,通过:
options.TokenValidationParameters = new TokenValidationParameters
{
ValidateIssuer = true,
ValidateIssuerSigningKey = true,
ValidateAudience = true,
ValidateLifetime = true,
ClockSkew = TimeSpan.Zero,
ValidIssuer = KeyCloakOptions.Authority
};
我不明白为什么现在在 .NET 8 中需要这一点,但在 .NET 7 中不需要。但是,即使如此,在进行上述更改后,我也会收到有关观众的类似错误,例如:
IDX10208:无法验证受众。 validationParameters.ValidAudience 为 null 或空格,validationParameters.ValidAudiences 为 null。
再次强调,这可以通过修改
TokenValidationParameters
以包含观众来克服:
options.TokenValidationParameters = new TokenValidationParameters
{
ValidateIssuer = true,
ValidateIssuerSigningKey = true,
ValidateAudience = true,
ValidateLifetime = true,
ClockSkew = TimeSpan.Zero,
ValidIssuer = KeyCloakOptions.Authority,
ValidAudience = KeycloakOptions.AudienceInvoice
};
这将导致下一个有关签名密钥的错误。对于这个,我不知道我需要做什么才能让它发挥作用。
我的主要问题是,为什么我现在需要在
TokenValidationParameters
中包含诸如发行者、受众和密钥之类的内容,而之前它作为选项的一部分运行良好。似乎某些选项(例如 options.MetadataAddress
)在 .NET 8 中被忽略,这就是为什么我现在需要显式指定 TokenValidationParameters
中的值。
或者也许是一个更基本的问题,是否需要添加/修改一些内容,以便在 .NET 7 中工作的相同(或非常相似的代码)也可以在 .NET 8 中工作。
感谢您的帮助, 埃里克
以下内容对我有用,这很好,尽管我不清楚为什么需要进行此更改。修复本质上是将所有验证逻辑移至 TokenValidationParameters 中。
即代码改为:
options.TokenValidationParameters = new TokenValidationParameters
{
ValidateIssuer = true,
ValidateIssuerSigningKey = true,
ValidateAudience = true,
ValidateLifetime = true,
ClockSkew = TimeSpan.Zero
};
// These properties need to be moved to TokenValidationParameters
options.Authority = KeyCloakOptions.Authority;
options.MetadataAddress = $"{options.Authority}/.well-known/openid-configuration";
options.RequireHttpsMetadata = false;
options.RefreshOnIssuerKeyNotFound = true;
options.Audience = KeycloakOptions.AudienceInvoice;
至:
options.TokenValidationParameters = new TokenValidationParameters
{
ValidateIssuer = true,
ValidateIssuerSigningKey = true,
ValidateAudience = true,
ValidateLifetime = true,
ClockSkew = TimeSpan.Zero,
ValidAudience = KeycloakOptions.AudienceInvoice,
ValidIssuer = issuer,
ConfigurationManager = new ConfigurationManager<OpenIdConnectConfiguration>(
$"{KeyCloakOptions.Authority}/.well-known/openid-configuration",
new OpenIdConnectConfigurationRetriever(),
new HttpDocumentRetriever() { RequireHttps = false }
)
};
我的理解是,这将提供与我现在相同的行为,但我仍然想了解为什么需要进行此更改(假设这是正确的更改)。