问题描述
现在我正在尝试在 Blazor WASM 中实现绝对基本的(假)身份验证。我使用 .Net 5.0 和身份验证创建了一个 Visual Studio“Blazor Webassembly App”项目。 除了 Index.razor 之外,我删除了 .razor 文件,它得到了以下实现
@page "/"
@inherits DataLayerGeneratorClient.Pages.Main.IndexBase
@using Microsoft.AspNetCore.Components.Authorization
@using Microsoft.AspNetCore.Components.WebAssembly.Authentication
<AuthorizeView>
<Authorized>
Hello,@context.User.Identity.Name!
<button class="nav-link btn btn-link" @onclick="logout">
Log out
</button>
</Authorized>
<NotAuthorized>
<table>
<tr>
<td>User</td>
<td><input type="text" @bind="AuthenticationStateProvider.User" /></td>
</tr>
<tr>
<td>Password</td>
<td><input type="text" @bind="AuthenticationStateProvider.Password" /></td>
</tr>
</table>
<br />
<button @onclick="Login">Login</button>
</NotAuthorized>
</AuthorizeView>
和 IndexBase.cs
public class IndexBase : LayoutComponentBase
{
[Inject]
public IHttpClientFactory HttpClientFactory { get; set; }
[Inject]
public CustomAuthenticationStateProvider AuthenticationStateProvider { get; set; }
public async Task Login(MouseEventArgs e)
{
using (HttpClient client = HttpClientFactory.CreateClient("ServerAPI"))
{
...
}
}
}
我也做了一个 CustomAuthenticationStateProvider
public class CustomAuthenticationStateProvider : AuthenticationStateProvider
{
public override Task<AuthenticationState> GetAuthenticationStateAsync()
{
//Login Failed
return Task.Fromresult(new AuthenticationState(new ClaimsPrincipal(new ClaimsIdentity())));
//Login succeeded
//Claim claim = new Claim(ClaimTypes.Name,"TestUser");
//ClaimsIdentity claimsIdentity = new ClaimsIdentity(new[] { claim },"fake auth");
//ClaimsPrincipal claimsPrincipal = new ClaimsPrincipal(claimsIdentity);
//AuthenticationState authenticationState = new AuthenticationState(claimsPrincipal);
//return Task.Fromresult(authenticationState);
}
}
和一个 CustomAuthorizationMessageHandler
public class CustomAuthorizationMessageHandler : AuthorizationMessageHandler
{
private readonly CustomAuthenticationStateProvider _customAuthenticationStateProvider;
public CustomAuthorizationMessageHandler(IAccesstokenProvider provider,NavigationManager navigation,CustomAuthenticationStateProvider customAuthenticationStateProvider) : base(provider,navigation)
{
if (customAuthenticationStateProvider == null)
{
throw new ArgumentNullException(nameof(customAuthenticationStateProvider));
}
_customAuthenticationStateProvider = customAuthenticationStateProvider;
}
...
}
在 App.razor 中,我更改了 DefaultLayout
DefaultLayout="@typeof(Index)"
最后这里是来自 Program.cs 的 Main
public static async Task Main(string[] args)
{
var builder = WebAssemblyHostBuilder.CreateDefault(args);
builder.RootComponents.Add<App>("#app");
builder.Services.AddApiAuthorization();
builder.Services.AddAuthorizationCore();
builder.Services.AddScoped<CustomAuthenticationStateProvider>();
builder.Services.AddScoped<AuthenticationStateProvider,CustomAuthenticationStateProvider>();
builder.Services.AddScoped<CustomAuthorizationMessageHandler>();
builder.Services.AddScoped<AuthorizationMessageHandler,CustomAuthorizationMessageHandler>();
builder.Services.AddHttpClient("ServerAPI").AddHttpMessageHandler(sp =>
{
return sp.GetService<CustomAuthorizationMessageHandler>().ConfigureHandler(authorizedUrls: new[] { "http://localhost:10000" });
});
builder.Services.AddScoped(serviceProvider => serviceProvider.GetrequiredService<IHttpClientFactory>().CreateClient("ServerAPI"));
await builder.Build().RunAsync();
}
问题来了。一旦 IHttpClientFactory.CreateHttpClient 被执行,它就会失败并显示错误“指定的强制转换无效”。 哪个演员表无效?
编辑 1 注入 HttpClient 而不是 IHttpClientFactory 似乎不是答案。当我测试它时,错误只是在启动时出现,而不是在单击按钮时出现。如果有帮助,这里又是堆栈跟踪
system.invalidCastException: Specified cast is not valid.
at Microsoft.Extensions.DependencyInjection.WebAssemblyAuthenticationServiceCollectionExtensions.<>c__0`3[[Microsoft.AspNetCore.Components.WebAssembly.Authentication.RemoteAuthenticationState,Microsoft.AspNetCore.Components.WebAssembly.Authentication,Version=5.0.2.0,Culture=neutral,PublicKeyToken=adb9793829ddae60],[Microsoft.AspNetCore.Components.WebAssembly.Authentication.RemoteUserAccount,[Microsoft.AspNetCore.Components.WebAssembly.Authentication.ApiAuthorizationProviderOptions,PublicKeyToken=adb9793829ddae60]].<AddRemoteAuthentication>b__0_1(IServiceProvider sp)
at Microsoft.Extensions.DependencyInjection.ServiceLookup.CallSiteRuntimeResolver.VisitFactory(FactoryCallSite factoryCallSite,RuntimeResolverContext context)
at Microsoft.Extensions.DependencyInjection.ServiceLookup.CallSiteVisitor`2[[Microsoft.Extensions.DependencyInjection.ServiceLookup.RuntimeResolverContext,Microsoft.Extensions.DependencyInjection,Version=5.0.0.1,[System.Object,System.Private.CoreLib,Version=5.0.0.0,PublicKeyToken=7cec85d7bea7798e]].VisitCallSiteMain(ServiceCallSite callSite,RuntimeResolverContext argument)
at Microsoft.Extensions.DependencyInjection.ServiceLookup.CallSiteRuntimeResolver.VisitCache(ServiceCallSite callSite,RuntimeResolverContext context,ServiceProviderEnginescope serviceProviderEngine,RuntimeResolverLock lockType)
at Microsoft.Extensions.DependencyInjection.ServiceLookup.CallSiteRuntimeResolver.VisitScopeCache(ServiceCallSite singletonCallSite,PublicKeyToken=7cec85d7bea7798e]].VisitCallSite(ServiceCallSite callSite,RuntimeResolverContext argument)
at Microsoft.Extensions.DependencyInjection.ServiceLookup.CallSiteRuntimeResolver.VisitConstructor(ConstructorCallSite constructorCallSite,RuntimeResolverContext argument)
at Microsoft.Extensions.DependencyInjection.ServiceLookup.CallSiteRuntimeResolver.Resolve(ServiceCallSite callSite,ServiceProviderEnginescope scope)
at Microsoft.Extensions.DependencyInjection.ServiceLookup.RuntimeServiceProviderEngine.<>c__displayClass1_0.<RealizeService>b__1(ServiceProviderEnginescope p)
at Microsoft.Extensions.DependencyInjection.ServiceLookup.RuntimeServiceProviderEngine.<>c__displayClass1_0.<RealizeService>b__0(ServiceProviderEnginescope scope)
at Microsoft.Extensions.DependencyInjection.ServiceLookup.ServiceProviderEngine.GetService(Type serviceType,ServiceProviderEnginescope serviceProviderEnginescope)
at Microsoft.Extensions.DependencyInjection.ServiceLookup.ServiceProviderEnginescope.GetService(Type serviceType)
at Microsoft.Extensions.DependencyInjection.ServiceProviderServiceExtensions.GetService[CustomAuthorizationMessageHandler](IServiceProvider provider)
at DataLayerGeneratorClient.Program.<>c.<Main>b__0_0(IServiceProvider sp) in D:\Dev\4.0\Test2\DataLayerGenerat…tem.Lazy`1[[Microsoft.Extensions.Http.ActiveHandlerTrackingEntry,Microsoft.Extensions.Http,PublicKeyToken=adb9793829ddae60]].ExecutionAndPublication(LazyHelper executionAndPublication,Boolean useDefaultConstructor)
at System.Lazy`1[[Microsoft.Extensions.Http.ActiveHandlerTrackingEntry,PublicKeyToken=adb9793829ddae60]].CreateValue()
at System.Lazy`1[[Microsoft.Extensions.Http.ActiveHandlerTrackingEntry,PublicKeyToken=adb9793829ddae60]].get_Value()
at Microsoft.Extensions.Http.DefaultHttpClientFactory.CreateHandler(String name)
at Microsoft.Extensions.Http.DefaultHttpClientFactory.CreateClient(String name)
at DataLayerGeneratorClient.Program.<>c.<Main>b__0_1(IServiceProvider serviceProvider) in D:\Dev\4.0\Test2\DataLayerGeneratorClient\Program.cs:line 32
at Microsoft.Extensions.DependencyInjection.ServiceLookup.CallSiteRuntimeResolver.VisitFactory(FactoryCallSite factoryCallSite,ServiceProviderEnginescope serviceProviderEnginescope)
at Microsoft.Extensions.DependencyInjection.ServiceLookup.ServiceProviderEnginescope.GetService(Type serviceType)
at Microsoft.AspNetCore.Components.ComponentFactory.<>c__displayClass6_0.<CreateInitializer>g__Initialize|2(IServiceProvider serviceProvider,IComponent component)
at Microsoft.AspNetCore.Components.ComponentFactory.PerformPropertyInjection(IServiceProvider serviceProvider,IComponent instance)
at Microsoft.AspNetCore.Components.ComponentFactory.InstantiateComponent(IServiceProvider serviceProvider,Type componentType)
at Microsoft.AspNetCore.Components.RenderTree.Renderer.InstantiateComponent(Type componentType)
at Microsoft.AspNetCore.Components.RenderTree.Renderer.InstantiateChildComponentOnFrame(RenderTreeFrame& frame,Int32 parentComponentId)
at Microsoft.AspNetCore.Components.RenderTree.RenderTreeDiffBuilder.InitializeNewComponentFrame(DiffContext& diffContext,Int32 frameIndex)
at Microsoft.AspNetCore.Components.RenderTree.RenderTreeDiffBuilder.InitializeNewSubtree(DiffContext& diffContext,Int32 frameIndex)
at Microsoft.AspNetCore.Components.RenderTree.RenderTreeDiffBuilder.InsertNewFrame(DiffContext& diffContext,Int32 newFrameIndex)
at Microsoft.AspNetCore.Components.RenderTree.RenderTreeDiffBuilder.AppendDiffEntriesForRange(DiffContext& diffContext,Int32 oldStartIndex,Int32 oldEndindexExcl,Int32 newStartIndex,Int32 newEndindexExcl)
at Microsoft.AspNetCore.Components.RenderTree.RenderTreeDiffBuilder.ComputeDiff(Renderer renderer,RenderBatchBuilder batchBuilder,Int32 componentId,ArrayRange`1 oldTree,ArrayRange`1 newTree)
at Microsoft.AspNetCore.Components.Rendering.ComponentState.RenderIntoBatch(RenderBatchBuilder batchBuilder,RenderFragment renderFragment)
at Microsoft.AspNetCore.Components.RenderTree.Renderer.RenderInExistingBatch(RenderQueueEntry renderQueueEntry)
at Microsoft.AspNetCore.Components.RenderTree.Renderer.ProcessRenderQueue()…
编辑 2 一旦我删除了对 CustomAuthenticationStateProvider 的任何引用,错误就消失了。但这有什么意义呢?
编辑 3 我通过删除 AddApiAuthorization 并实现自定义 HttpMessageHandler 而不是 cucstom AuthorizationMessageHandler 来使其工作
解决方法
暂无找到可以解决该程序问题的有效方法,小编努力寻找整理中!
如果你已经找到好的解决方法,欢迎将解决方案带上本链接一起发送给小编。
小编邮箱:dio#foxmail.com (将#修改为@)