在我的 .NET 8 Blazor Web 应用程序中,我使用“个人帐户”对用户进行身份验证(因此我使用
Microsoft Identity
)。我有一个服务器和一个客户端项目。我有一些想要保护的端点:这些端点是文件夹 Controllers
下服务器项目中的最小 API。例如,
public static void MapClientEndpoints (this IEndpointRouteBuilder routes)
{
var group = routes.MapGroup("/api/Client").WithTags(nameof(Client));
group.MapGet("/", async (HypnoContext db) =>
{
return await db.Client.ToListAsync();
})
.RequireAuthorization()
.WithName("GetAllClients")
.WithOpenApi();
}
在
Program.cs
中,我为HttpClient
添加了以下代码:
builder.Services.AddScoped<CustomAuthorizationMessageHandler>();
builder.Services.AddHttpClient("ServerAPI", client => {
client.BaseAddress = new Uri(builder.Configuration["FrontendUrl"]);
})
.AddHttpMessageHandler<CustomAuthorizationMessageHandler>();
builder.Services.AddTransient(sp =>
sp.GetRequiredService<IHttpClientFactory>().CreateClient("ServerAPI"));
CustomAuthorizationMessageHandler
如下
public class CustomAuthorizationMessageHandler : AuthorizationMessageHandler
{
public CustomAuthorizationMessageHandler(IAccessTokenProvider provider,
NavigationManager navigationManager)
: base(provider, navigationManager)
{
ConfigureHandler(
authorizedUrls: new[] { "https://localhost:7241" });
}
}
我这样做是因为我想调用受个人帐户保护的服务器项目中公开的 API。所以,在一个页面中
@inject HttpClient httpClient
HttpRequestMessage request = new HttpRequestMessage(
HttpMethod.Get, "/api/Client");
await httpClient.SendAsync(request);
当我运行应用程序时,我立即收到错误:
System.AggregateException:“某些服务无法 构造(验证服务描述符时出错 '服务类型:MyApp.CustomAuthorizationMessageHandler 生命周期:范围实施类型: MyApp.CustomAuthorizationMessageHandler':无法解析 类型服务 'Microsoft.AspNetCore.Components.WebAssembly.Authentication.IAccessTokenProvider' 尝试激活时 'MyApp.CustomAuthorizationMessageHandler'。)'
所以,我尝试添加以下代码
builder.Services.AddAuthentication(JwtBearerDefaults.AuthenticationScheme)
.AddJwtBearer(options =>
{
options.TokenValidationParameters = new TokenValidationParameters
{
ValidateIssuer = true,
ValidateAudience = true,
ValidateLifetime = true,
ValidateIssuerSigningKey = true,
ValidIssuer = builder.Configuration["JwtIssuer"],
ValidAudience = builder.Configuration["JwtAudience"],
IssuerSigningKey = new SymmetricSecurityKey(Encoding.UTF8.GetBytes(
builder.Configuration["JwtSecurityKey"]))
};
});
但这没有帮助。我错过了什么?
System.AggregateException:“某些服务无法 构造(验证服务描述符时出错 'ServiceType:MyApp.CustomAuthorizationMessageHandler 生命周期:作用域 实现类型:MyApp.CustomAuthorizationMessageHandler':无法 解决类型的服务 'Microsoft.AspNetCore.Components.WebAssembly.Authentication.IAccessTokenProvider' 尝试激活时 'MyApp.CustomAuthorizationMessageHandler'。)'
IAccessTokenProvider
通常由RemoteAuthenticationServiceAddOidcAuthentication
中的AddMsalAuthentication
或Program.cs
添加。 CustomAuthorizationHandler
重现不使用服务器端 OIDC 身份验证。这意味着任何地方都没有注册 IAccessTokenProvider
。
为了实现您的要求,您需要使用 BFF 模式从加密 cookie 中提取令牌,如 使用 OpenID Connect (OIDC) 保护 ASP.NET Core Blazor Web 应用程序 或传输未加密的访问使用 PersistentComponentState 向客户端发送令牌,如 mohaaron/CustomAuthorizationHandler#1 中所示。我认为 BFF 模式是两者中更好的选择。