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

发布于 2025-02-04 03:44:00 字数 186 浏览 1 评论 0 原文

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

但是,我仍然希望现有的授权框架工作。换句话说,我希望能够使用授权> @attribute [授权] 来维护安全性。

我已经搜索和搜索过,但没有找到有关如何实施此操作的任何详细信息。

I would like to bypass AspnetCore identity completely, and instead use a custom method of Authenticating the current user.

However, I would still like the existing Authorization framework to work. In other words, I want to be able to use the AuthorizeView and @attribute [Authorize] to maintain security.

I have searched and searched but am not finding any details on how to implement this.

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(2

允世 2025-02-11 03:44:00

好的,因此您想在Blazor Server应用程序中实现自定义身份验证。换句话说,您想使用与ASP.NET身份不同的方法进行注册和身份验证用户。但是,您仍然需要使用授权好品(例如授权视图和 [授权] 属性)属性。

请注意,我在这里说的仅适用于Blazor Server应用程序。如果您使用的是Glazor WebAssembly,则需要一个不同的解决方案,该解决方案是完全不同的安全模型。

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

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

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.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;
    }
}

在您的实现中,当然,您需要在您认为合适的情况下授权用户。

免责声明:以任何方式我都不是安全专家。除了我吃午餐时,除了短暂的烟雾测试外,以上没有测试。

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

但是,有了以上,内置的授权框架起作用,包括角色。

Ok, so you want to implement Custom Authentication in your Blazor Server app. In other words, you want to use a different method than ASP.net Identity to register and authenticate users. But you still want to use the built in Authorization goodies such as AuthorizedView and the [Authorize] attribute on your pages.

Note that what I say here is only applicable to a Blazor Server App. If you are using a Blazor Webassembly, you need a different solution which is not covered here, as it is a completely different security model.

Ok, to get started: To implement Custom Authentication, you need to implement a class called AuthenticationStateProvider.

Here is the link to the docs for creating a Custom AuthenticationStateProvider. However, the docs don't give a complete solution, so here is the rest of it based on the 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;
    }
}

After this is in place, register it in program.cs, and comment out the existing one:

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

Now you are ready to use it to log your user in:

<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;
    }
}

In your implementation, of course you need to authorize your user as you see fit.

Disclaimer: I am not a security expert in any way. The above has not been tested other than a brief smoke test while I had lunch.

Note that this does not keep the user closes the page, or refreshes the page.

However, with the above in place, the built in Authorization framework works, including roles.

摇划花蜜的午后 2025-02-11 03:44:00

确实,所有信息在文档中都非常分散。
这就是为什么我创建此示例的原因。

https://github.com/iso88859/aspnetcoreauthmultilang

在文件的最后,请使用myServerauterauthectateprication cantateprication cantateprication cantateprication cantateprication cantateprication cantateProvider。角色。

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"
            )));

Indeed, all the information is quite fragmented in the documentation.
That's why I created this example.

https://github.com/iso8859/AspNetCoreAuthMultiLang

At the end of file myServerAuthenticationStateProvider.cs you can play with roles.

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"
            )));
~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文