如何在 Blazor Server 中实现自定义授权

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

我想完全绕过 AspnetCore 身份,而是使用对当前用户进行身份验证的自定义方法。

但是,我仍然希望现有的授权框架能够发挥作用。换句话说,我希望能够使用

AuthorizeView
@attribute [Authorize]
来维护安全。

我搜索了又搜索,但没有找到任何有关如何实现此操作的详细信息。

c# asp.net-core blazor blazor-server-side
3个回答
12
投票

好的,您想在 Blazor Server 应用程序中实现自定义身份验证。换句话说,您希望使用与 ASP.net Identity 不同的方法来注册和验证用户。但您仍然希望在页面上使用内置的

Authorization
功能,例如 AuthorizedView 和
[Authorize]
属性。

请注意,我在这里所说的仅适用于 Blazor 服务器应用程序。如果您使用 Blazor Web assembly,则需要不同的解决方案,此处未介绍,因为它是完全不同的安全模型。

好的,开始吧:要实现自定义身份验证,您需要实现一个名为

AuthenticationStateProvider
的类。

这里是用于创建自定义 AuthenticationStateProvider 的 docs 的链接。但是,文档没有给出完整的解决方案,因此这里是基于文档的其余部分:

public class CustomAuthenticationStateProvider : AuthenticationStateProvider
{
    public CustomAuthenticationStateProvider()
    {
        this.CurrentUser = this.GetAnonymous();
    }

    private ClaimsPrincipal CurrentUser { get; set; }

    private ClaimsPrincipal GetUser(string userName, string id, string role)
    {
        var identity = new ClaimsIdentity(new[]
        {
            new Claim(ClaimTypes. Sid, id),
            new Claim(ClaimTypes.Name, userName),
            new Claim(ClaimTypes.Role, role)
        }, "Authentication type");
        return new ClaimsPrincipal(identity);
    }

    private ClaimsPrincipal GetAnonymous()
    {
        var identity = new ClaimsIdentity(new[]
        {
            new Claim(ClaimTypes.Sid, "0"),
            new Claim(ClaimTypes.Name, "Anonymous"),
            new Claim(ClaimTypes.Role, "Anonymous")
        }, null);
        return new ClaimsPrincipal(identity);
    }

    public override Task<AuthenticationState> GetAuthenticationStateAsync()
    {
        var task = Task.FromResult(new AuthenticationState(this.CurrentUser));
        return task;
    }

    public Task<AuthenticationState> ChangeUser(string username, string id, string role)
    {
        this.CurrentUser = this.GetUser(username, id, role);
        var task = this.GetAuthenticationStateAsync();
        this.NotifyAuthenticationStateChanged(task);
        return task;
    }

    public Task<AuthenticationState> Logout()
    {
        this.CurrentUser = this.GetAnonymous();
        var task = this.GetAuthenticationStateAsync();
        this.NotifyAuthenticationStateChanged(task);
        return task;
    }
}

完成后,在program.cs中注册它,并注释掉现有的:

builder.Services.AddScoped<AuthenticationStateProvider, CustomAuthenticationStateProvider>();
//builder.Services.AddScoped<AuthenticationStateProvider, RevalidatingIdentityAuthenticationStateProvider<IdentityUser>>();

现在您可以使用它来登录您的用户:

<AuthorizeView>
    <Authorized>
        <div class="m-1 p-1 text-white">
            Welcome,  @user.Identity.Name
        </div>
    </Authorized>
    <NotAuthorized>
        <div>
            <div>
                Your email<input type="text" @bind-value="@Email" />
            </div>
            <div>
                Your password<input type="text" @bind-value="@Password" />
            </div>
            <div>
                <button style="width:70px;"  @onclick="Login">Submit</button>
            </div>
        </div>
    </NotAuthorized>
</AuthorizeView>

@code{
    public string Email { get; set; }

    public string Password { get; set; }

    public string Id { get; set; } = "12345";

    [CascadingParameter] public Task<AuthenticationState> AuthTask { get; set; }

    [Inject] private AuthenticationStateProvider AuthState { get; set; }

    private System.Security.Claims.ClaimsPrincipal user;

    protected async override Task OnInitializedAsync()
    {
        var authState = await AuthTask;
        this.user = authState.User;
    }

    public async Task Login()
    {
        //Todo:  Validate against actual database.
        var authState = await ((CustomAuthenticationStateProvider)AuthState).ChangeUser(this.Email, this.Id, "Associate");
        this.user = authState.User;
    }
}

在您的实现中,当然您需要根据您认为合适的方式授权您的用户。

免责声明:我无论如何都不是安全专家。除了我吃午饭时进行的简短烟雾测试之外,上述内容尚未经过测试。

请注意,这不会让用户关闭页面或刷新页面。

但是,完成上述操作后,内置的授权框架(包括角色)就可以工作了。


4
投票

确实,文档中的所有信息都相当分散。 这就是我创建这个示例的原因。

https://github.com/iso8859/AspNetCoreAuthMultiLang

在文件 myServerAuthenticationStateProvider.cs 的末尾,您可以扮演角色。

result = new AuthenticationState(
                new ClaimsPrincipal(
                    new ClaimsIdentity(new[] { 
                        new Claim(ClaimTypes.Name, m_login),
                        new Claim(ClaimTypes.Role, "demo_role"),
                        new Claim(ClaimTypes.Role, "Admin"),
                    }, "PutAppNameHere"
            )));

0
投票

这篇文章似乎很旧,但我也开始将 Azure B2C 与 Blazor 服务器 .net 8 集成,并想知道是否有一种方法可以为经过身份验证的用户传递访问令牌,而无需将其保存在应用程序中的某个位置。 就像下面的代码一样,我有 blazor wasm .net6 公共类 CustomAuthorizationMessageHandler : AuthorizationMessageHandler { 公共 CustomAuthorizationMessageHandler(IAccessTokenProvider 提供商, 导航管理器 (navigationManager) :基础(提供者,导航管理器) { 配置处理程序( authorizedUrls: new[] { BaseUri }); } }

但是 AuthorizationMessageHandler 类用于 Web 程序集,是否有类似的设置可以与 blazor 服务器一起使用。我需要访问令牌才能附加到我的安全休息 API。

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