在 Razor <AuthorizeView> 标签看来,注销 ClaimsIdentity(IsAuthenticated 为 false)的首选方式是什么?

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

我正在我的 Blazor 应用程序中构建一个简单的自定义身份验证方法。登录用户必须通过 Razor

<AuthorizeView>
属性才能看到这几个页面。

我可以通过向

ClaimsPrincipal
(通过级联
AuthenticationState
获得)添加一个具有非空身份验证类型的新
ClaimsIdentity
(这是
AuthorizeView
属性在没有
 时使用的信息)来使其工作。指定了 Role
Policy
,请参阅 为什么我的 ClaimsIdentity IsAuthenticated 始终为 false(对于 Web api 授权过滤器)?)。但是当我想“注销”用户时,我无法删除该“经过身份验证的”ClaimsIdentity。

我找到的解决方法是在主体登录时将名为“loggedin”的角色插入主体(通过新的

ClaimsIdentity
),并在他注销时从相关的
ClaimsIdentity
中拔出该角色。控制可见性的 Razor 属性就是
<AuthorizeView Role="loggedin">
。我也可以使用
Policy
,但两者对我来说都显得很脏,因为在这里我只希望页面在用户经过身份验证时可见(而不是“授权”,角色和策略是为这些角色和策略而制定的,我发现这个概念应该与单纯的身份验证区分开来)。但也许这是正确的做法,我不知道。

那么,指定页面仅对经过身份验证的用户可见(没有其他条件)并控制用户的身份验证状态的最简洁方法是什么,仅使用 Razor

AuthorizeView
属性(和子属性),
ClaimsPrincipal 
ClaimsIdentity

c# asp.net-core authentication blazor claims-based-identity
1个回答
0
投票

由于您的问题很少涉及代码,因此这里有一个有关如何执行我认为您想要的操作的演示。这是基于 Blazor 服务器。

它使用自定义的

AuthenticationStateProvider
来捕获原始用户并存储声明。然后,您可以使用捕获的声明构建您自己的
ClaimsIdentity
ClaimsPrincipal
。如果您的委托人拥有多个身份,您将需要编写代码来捕获该身份。

自定义身份验证状态提供者:

public class MyAuthenticationProvider : ServerAuthenticationStateProvider
{
    ClaimsPrincipal? _user;
    IEnumerable<Claim>? _claims;

    public async override Task<AuthenticationState> GetAuthenticationStateAsync()
    {
        var authState = await base.GetAuthenticationStateAsync();

        var user = authState.User;
        if (user.Identity?.IsAuthenticated ?? false)
            _claims = user.Identities.FirstOrDefault()?.Claims ?? Enumerable.Empty<Claim>();

        return authState;
    }

    public Task LogOutIdentityAsync()
    {
        _user = new ClaimsPrincipal(new ClaimsIdentity(_claims, null));
        var newState = new AuthenticationState(_user);
        this.NotifyAuthenticationStateChanged(Task.FromResult<AuthenticationState>(newState));
        return Task.CompletedTask;
    }

    public Task LogInIdentityAsync()
    {
        _user = new ClaimsPrincipal(new ClaimsIdentity(_claims, "nlm"));
        var newState = new AuthenticationState(_user);
        this.NotifyAuthenticationStateChanged(Task.FromResult<AuthenticationState>(newState));
        return Task.CompletedTask;
    }
}

已注册:

// at the end of services definitions
builder.Services.AddScoped<AuthenticationStateProvider, MyAuthenticationProvider>();

用于切换身份验证的演示布局。

@inherits LayoutComponentBase
@inject AuthenticationStateProvider _authProvider

<PageTitle>BlazorApp1</PageTitle>

<div class="page">
    <div class="sidebar">
        <NavMenu />
    </div>

    <main>
        <div class="top-row px-4 auth">
            <button class="btn btn-primary" @onclick="ToggleAuth">Toggle</button>
            <LoginDisplay />
            <a href="https://docs.microsoft.com/aspnet/" target="_blank">About</a>
        </div>

        <article class="content px-4">
            @Body
        </article>
    </main>
</div>

@code {
    bool _authState = true;

    void ToggleAuth()
    {
        if (_authState)
            ((MyAuthenticationProvider)_authProvider).LogOutIdentityAsync();
        else
            ((MyAuthenticationProvider)_authProvider).LogInIdentityAsync();

        _authState = !_authState;
    }
}
© www.soinside.com 2019 - 2024. All rights reserved.