自定义认证状态提供商返回 "空用户"

问题描述 投票:0回答:1

在我们的应用程序中,我想使用我们胖客户端的用户管理。为此我写了一个自定义的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属性为真。

然而,当使用 "AuthorizeView "组件时,我总是得到一个 "空用户"(没有名称声明,没有用户名,IsAuthenticated为假)。

我现在有一个小组件,只是为了测试。

<AuthorizeView>
<Authorized>
    <h2>User @context.User.Identity.Name</h2> is logged in!
    Claims:
    <ul>
        @foreach (var claim in context.User.Claims)
        {
            <li>[email protected]; [email protected]</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:/docs.microsoft.comen-usaspnetcoresecurityblazor?view=aspnetcore-3.1。

通过CascadingParameter访问AuthenticationState的结果也是一样的 "空用户"。

感谢任何帮助。

倾斜32

编辑1

所以我又研究了一下登录行为,确保该事件被调用.然后我发现,我的AuthenticationStateChanged事件没有订阅者(是空的)。我的印象是,框架中的一些东西在启动时附加到这个事件上。也许我在启动时忘记了一些配置方法的调用?这就是我在配置服务中所做的。

    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(在加载屏幕期间)。

EDIT 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 app, IWebHostEnvironment env)方法中,我添加了以下调用。

app.UseAuthentication();
app.UseAuthorization();

这也没有任何效果

authentication server-side blazor
1个回答
1
投票

我认为AuthenticationState对象是不可用的,因为AuthenticationStateChanged事件没有从AuthenticationStateProvider中调用,因此你的AuthorizeView和你的CascadingAuthenticationState组件没有意识到状态的变化。在这个方向上再检查一次你的逻辑。同时确保你正确地将子类化的提供者添加到DI容器中。我倾向于认为问题出在这里。请展示ConfigureServices方法的所有相关代码。

更新:请你试试这个。

services.AddScoped<MyAuthenticationStateProvider>();
services.AddScoped<AuthenticationStateProvider>(provider => 
  provider.GetRequiredService<MyAuthenticationStateProvider>());

希望能帮到你...

© www.soinside.com 2019 - 2024. All rights reserved.