AuthenticationStateProvider 的初始状态

Initial state of AuthenticationStateProvider

the documentation 之后,我创建了自定义 AuthenticationStateProvider,如下所示:

public class ApiAuthStateProvider : AuthenticationStateProvider
{
    private static AuthenticationState anonymousState = ?

    private AuthenticationState _authState;

    public ApiAuthStateProvider()
    {
        _authState = anonymousState;
    }

    public void SetAuthenticationState(AuthenticationState authState)
    {
        _authState = authState ?? anonymousState;
        NotifyAuthenticationStateChanged(GetAuthenticationStateAsync());
    }

    public override Task<AuthenticationState> GetAuthenticationStateAsync()
    {
        return Task.FromResult(_authState);
    }
}

问题是如何初始化匿名状态,使_authState.User.Identity.IsAuthenticated为假。如文档中所示,以下将导致经过身份验证的用户:

private static AuthenticationState anonymousState = 
    new AuthenticationState(new ClaimsPrincipal(
    new ClaimsIdentity(new Claim[] {}, "none")));

即使是以下结果也是经过身份验证的用户:

public class AnonymousIdentity : IIdentity
{
    public string AuthenticationType => "none";
    public bool IsAuthenticated => false;
    public string Name => string.Empty;
}

private static AuthenticationState anonymousState;

static ApiAuthStateProvider()
{
    var anonymousIdentity = new AnonymousIdentity();
    var user = new ClaimsIdentity(anonymousIdentity);
    anonymousState = new AuthenticationState(
        new ClaimsPrincipal(user));
}

我在这里错过了什么?

嗯,在.net core source我发现

public virtual bool IsAuthenticated
{
    get { return !string.IsNullOrEmpty(_authenticationType); }
}

这意味着我应该像下面这样更改我的代码:

private static AuthenticationState anonymousState = 
    new AuthenticationState(new ClaimsPrincipal(
    new ClaimsIdentity(new Claim[] {}, "")));

    // Or, can be even shorter like below
    // private static AuthenticationState anonymousState = 
    //     new AuthenticationState(new ClaimsPrincipal());

这使我的 Blazor 应用无法正常显示,但我想这是另一个问题。

是的,只需使用:

new AuthenticationState(new ClaimsPrincipal());

这段代码对我有用:

    public class CustomAuthenticationProvider : AuthenticationStateProvider
    {
        private readonly HttpClient _httpClient;
        public CustomAuthenticationProvider(HttpClient httpClient)
        {
            _httpClient = httpClient;
        }
        public override async Task<AuthenticationState>
            GetAuthenticationStateAsync()
        {
            ClaimsPrincipal user;
            // Call the GetUser method to get the status
            // This only sets things like the AuthorizeView
            // and the AuthenticationState CascadingParameter
            var result =
                await _httpClient.GetJsonAsync<BlazorUser>("api/user/GetUser");
            // Was a UserName returned?
            if (result.UserName != "")
            {
                // Create a ClaimsPrincipal for the user
                var identity = new ClaimsIdentity(new[]
                {
                   new Claim(ClaimTypes.Name, result.UserName),
                }, "AzureAdAuth");
                user = new ClaimsPrincipal(identity);
            }
            else
            {
                user = new ClaimsPrincipal(); // Not logged in
            }
            return await Task.FromResult(new AuthenticationState(user));
        }
    }

参见:Client Side Blazor Authentication Using Azure AD and a Custom AuthenticationStateProvider