在我们的应用程序中,我想使用胖客户端的用户管理。为此,我编写了一个自定义AuthenticationStateProvider:
public class MyAuthenticationStateProvider : ServerAuthenticationStateProvider, IAuthentorizationService, IDisposable
{
public MyAuthenticationStateProvider (IPermissionManager permissionManager)
{
//User management service of the fat client
_permissionManager = permissionManager;
}
public override Task<AuthenticationState> GetAuthenticationStateAsync()
{
if (_permissionManager.PermissionUser == null)
{
var emptyUser = new ClaimsPrincipal(new ClaimsIdentity(new Claim[0]));
return Task.FromResult(new AuthenticationState(emptyUser));
}
var identity = new ClaimsIdentity(new[]
{
new Claim(ClaimTypes.Name, _permissionManager.PermissionUser.User.GetName())
}, "FatClientAuthentication");
var user = new ClaimsPrincipal(identity);
return Task.FromResult(new AuthenticationState(user));
}
public async Task<bool> LoginUser(string userName, string password)
{
//Login via WCF connection
var response = await _clientProxy.Login(new LoginRequest
{
LoginUserName = userName,
Password = password
});
response.LogExceptionIfFaulted(_logger);
if (response.Ok)
{
_permissionManager.Initialize(response.LoggedInUser);
NotifyAuthenticationStateChanged(GetAuthenticationStateAsync());
}
return response.Ok;
}
登录操作正常。出于测试目的,我总是使用固定的用户凭据登录。成功登录后,我触发NotifyAuthenticationStateChanged事件,从而正确调用GetAuthenticationStateAsync方法。现在登录的用户已正确封装在AuthenticationState中。调试代码时,我可以看到具有名称声明的Identity是正确的用户,并且IsAuthenticated属性为true。
然而,当使用"AuthorizeView"组件时,我总是得到一个"空用户"(没有名称声明,没有用户名,IsAuthenticated为false(
我现在有一个小组件只用于测试:
<AuthorizeView>
<Authorized>
<h2>User @context.User.Identity.Name</h2> is logged in!
Claims:
<ul>
@foreach (var claim in context.User.Claims)
{
<li>Type=@claim.Type; Value=@claim.Value</li>
}
</ul>
@context.User.Claims
<p>Current count: @currentCount</p>
<button class="btn btn-primary" @onclick="IncrementCount">Click me</button>
</Authorized>
<NotAuthorized>
<h2>User @context.User.Identity.Name</h2> @*this is an empty string*@
<h2>Authentication Type: @context.User.Identity.AuthenticationType</h2> @*empty*@
<h2>Authenticated: @context.User.Identity.IsAuthenticated</h2>@*false*@
No user is logged in!
</NotAuthorized>
我在App.razor中使用AuthorizeRouteView和CascadingAuthenticationState,类似于中显示的官方示例https://learn.microsoft.com/en-us/aspnet/core/security/blazor/?view=aspnetcore-3.1
通过CascadingParameter访问AuthenticationState也会导致相同的"空用户"。
感谢您的帮助,
倾斜32
编辑1
因此,我再次查看了登录行为,确保调用了该事件。然后我发现,我的AuthenticationStateChanged事件没有订阅者(为null(。我的印象是,框架中的某些东西与启动时的事件有关。也许我在启动时忘记了一些配置方法调用?这就是我在配置服务中所做的:
services.AddScoped<AuthenticationStateProvider, MyAuthenticationStateProvider>();
services.AddScoped<ServerAuthenticationStateProvider, MyAuthenticationStateProvider>();
//Interface which I use in my LoginCompontent and at Startup to log in with the default user or some real user credentials
services.AddScoped<IAuthenticationService, MyAuthenticationStateProvider>();
我还尝试了用户enet建议的方法。遗憾的是,没有成功,结果还是一样。在登录过程中,将调用NotifyAuthenticationStateChanged,从而调用没有订阅者的事件。
我们在后台使用的WCF服务需要一个登录用户。因此,我让一个权限有限的访客用户来解决这个问题。因此,该应用程序进入GetAuthenticationStateAsync,并尝试在启动后直接激发AuthenticationStateEvent(在加载屏幕期间(。
编辑2
因此,我现在尝试了一些额外的设置步骤,微软在Blazor文档中写道,这些步骤对于服务器端Blazor:来说应该是不必要的
ConfigureServices现在看起来像这个
//Authentication & Authorization setup
services.AddOptions();
services.AddAuthenticationCore();
services.AddAuthorizationCore();
services.AddScoped<IPermissionManager, SingleUserPermissionManager>();
services.AddScoped<AuthenticationStateProvider, MyAuthenticationStateProvider>();
services.AddScoped<ServerAuthenticationStateProvider, MyAuthenticationStateProvider>();
services.AddScoped<IAuthenticationService, MyAuthenticationStateProvider>();
在Configure(IApplicationBuilder应用程序,IWebHostEnvironment env(方法中,我添加了以下调用:
app.UseAuthentication();
app.UseAuthorization();
这也没有任何效果。
我认为AuthenticationState对象不可用,因为AuthenticationStateChanged事件不是从AuthenticationStateProvider调用的,因此AuthorizeView和CascadingAuthenticationState组件不知道状态更改。朝着这个方向再次检查你的逻辑。还要确保将子类化的提供程序正确添加到DI容器中。我倾向于认为问题在于此。请显示ConfigureServices方法中的所有相关代码。
更新:请试试这个:
services.AddScoped<MyAuthenticationStateProvider>();
services.AddScoped<AuthenticationStateProvider>(provider =>
provider.GetRequiredService<MyAuthenticationStateProvider>());
希望这能帮助。。。