我尝试应用 ASP.NET Core Blazor WebAssembly 额外的安全方案,键入
HttpClient
,并使用 OIDC 身份验证,如下所示,
// Blazor WebAssembly 'Program.cs'
public static async Task Main(string[] args)
{
var builder = WebAssemblyHostBuilder.CreateDefault(args);
builder.RootComponents.Add<App>("#app");
builder.Services.AddHttpClient<ApplicationHttpClient>(nameof(ApplicationHttpClient), client =>
{
client.BaseAddress = new Uri(builder.HostEnvironment.BaseAddress);
}).AddHttpMessageHandler<BaseAddressAuthorizationMessageHandler>();
builder.Services.AddScoped(serviceProvider =>
{
return serviceProvider.GetRequiredService<IHttpClientFactory>().CreateClient(nameof(ApplicationHttpClient));
});
builder.Services.AddOidcAuthentication<RemoteAuthenticationState, RemoteUserAccount>(options =>
{
builder.Configuration.Bind("Google", options.ProviderOptions);
options.ProviderOptions.DefaultScopes.Add("email");
}).AddAccountClaimsPrincipalFactory<RemoteAuthenticationState, RemoteUserAccount, CustomAccountClaimsPrincipalFactory>();
await builder.Build().RunAsync();
}
如果构建并运行,我遇到了以下异常,
crit: Microsoft.AspNetCore.Components.WebAssembly.Rendering.WebAssemblyRenderer[100]
Unhandled exception rendering component: ValueFactory attempted to access the Value property of this instance.
System.InvalidOperationException: ValueFactory attempted to access the Value property of this instance.
at System.Lazy`1[[Microsoft.Extensions.Http.ActiveHandlerTrackingEntry, Microsoft.Extensions.Http, Version=5.0.0.0, Culture=neutral, PublicKeyToken=adb9793829ddae60]].ViaFactory(LazyThreadSafetyMode mode) in System.Private.CoreLib.dll:token 0x6000fa7+0x43
at System.Lazy`1[[Microsoft.Extensions.Http.ActiveHandlerTrackingEntry, Microsoft.Extensions.Http, Version=5.0.0.0, Culture=neutral, PublicKeyToken=adb9793829ddae60]].ExecutionAndPublication(LazyHelper executionAndPublication, Boolean useDefaultConstructor) in System.Private.CoreLib.dll:token 0x6000fa8+0x22
at System.Lazy`1[[Microsoft.Extensions.Http.ActiveHandlerTrackingEntry, Microsoft.Extensions.Http, Version=5.0.0.0, Culture=neutral, PublicKeyToken=adb9793829ddae60]].CreateValue() in System.Private.CoreLib.dll:token 0x6000fad+0x74
at System.Lazy`1[[Microsoft.Extensions.Http.ActiveHandlerTrackingEntry, Microsoft.Extensions.Http, Version=5.0.0.0, Culture=neutral, PublicKeyToken=adb9793829ddae60]].get_Value() in System.Private.CoreLib.dll:token 0x6000fb3+0xa
at Microsoft.Extensions.Http.DefaultHttpClientFactory.CreateHandler(String name) in Microsoft.Extensions.Http.dll:token 0x6000065+0xe
at Microsoft.Extensions.Http.DefaultHttpClientFactory.CreateClient(String name) in Microsoft.Extensions.Http.dll:token 0x6000064+0xe
如果我注释掉
AddHttpMessageHandler<BaseAddressAuthorizationMessageHandler>()
,它会像以前一样运行良好。
.NET 6.0.100-预览版.5 21302.13
Visual Studio 2019 16.10.2
异常来自
DefaultHttpClientFactory.cs
。
// Microsoft.Extensions.Http.DefaultHttpClientFactory.cs
public HttpMessageHandler CreateHandler(string name)
{
if (name == null)
{
throw new ArgumentNullException(nameof(name));
}
// Here
ActiveHandlerTrackingEntry entry = _activeHandlers.GetOrAdd(name, _entryFactory).Value;
StartHandlerEntryTimer(entry);
return entry.Handler;
}
我用
AddHttpMessageHandler
测试 NoobHandler
方法,如下所示。
public class NoobHandler : DelegatingHandler
{
}
改为
BaseAddressAuthorizationMessageHandler
,添加 NoobHandler
即可。
builder.Services.AddScoped<NoobHandler>();
builder.Services.AddHttpClient<WeatherForecastClient>(nameof(WeatherForecastClient),
client => client.BaseAddress = new Uri(builder.HostEnvironment.BaseAddress))
.AddHttpMessageHandler<NoobHandler>();
因此,我怀疑
BaseAddressAuthorizationMessageHandler
构造函数没有创建实例,但DefaultHttpClientFactory
尝试访问值。
这是我一直在寻找的问题根源: https://github.com/dotnet/aspnetcore/issues/33787#issuecomment-1788625106
HttpClient 的循环依赖注入可能会导致这种情况。比如这样:
builder.Services.AddScoped<AuthenticationService>();
builder.Services.AddScoped<AppHttpMessageHandler>();
builder.Services.AddHttpClient("MyApi", client => client.BaseAddress = new Uri(ApiBaseAddress))
.AddHttpMessageHandler<AppHttpMessageHandler>();
如果您尝试将
HttpClient
注入 AuthenticationService
或 AppHttpMessageHandler
,您将收到此错误:
ValueFactory attempted to access the Value property of this instance
尝试使用
IHttpClientFactory
独立服务来解决此问题。