如何在Blazor Server应用中自定义默认Windows AutheticationStateProvider?

发布于 2025-02-10 03:01:10 字数 1602 浏览 0 评论 0原文

我有一个使用Windows身份验证来识别用户的Blazor Server应用程序。 该应用程序“检测”用户当前正在浏览该应用程序,并且可以正确显示域/用户名。

我写了一个课程,该课程检查了登录用户名并从数据库中获取角色,然后更新当前的主体,以便UI可以正确利用用户的给定角色。

由于我无法在此处共享的原因,我避免了实体框架和核心身份脚手架代码。

这是我写的课程,

public class CompanyAuthentication
{
    public CompanyAuthentication(AuthenticationStateProvider auth)
    {
        var result = auth.GetAuthenticationStateAsync().Result;
        // here I have access to the current username:
        string username = result.User.Identity.Name;
        // now I can fetch roles from file, but for simplicity, I will use the following:
        if(username.BeginsWith("admin"))
        {
            var claims = new ClaimsIdentity(new Claim[] {new Claim(ClaimType.Role, "admin")});
            result.User.AddIdentity(claims);  // this will have an effect on UI
        }
     
    }
}

还将上面的课程添加为启动

services.AddScoped<CompanyAuthentication>();

@page "/counter"
@inject CompanyAuthentication auth

<AuthorizeView Roles="admin">
    <Authorized> Welcome admin </Authorized>
    <NotAuthorized> You are not authorized </NotAuthorized>
</AuthorizeView>

我 /代码>在我打算使用的每个页面中。

有没有办法可以自动将我的课程注入每个页面而无需进行@Inject? 我知道我可以编写一个自定义身份验证类,该类别继承authenticationStateProvider,然后将其添加为服务,但是如果这样做,我将无法访问当前登录的用户名,因此,我可以'从数据库中提取角色。

我尝试使用httpcontext.current.user.inderity.name,但这不在Balzor Server应用程序中的任何部分的范围中。

如何利用Windows AuthenticationStateProvider,同时自定义角色,而不必在任何地方注入自定义化?

I have a Blazor Server app that uses Windows authentication to identify users.
The app "detects" the user currently browsing the app and can display domain/username correctly.

I wrote a class that checks logged in username and fetches roles from a database, then updates the current principal so that the UI can properly take advantage of the given roles for the user.

I am avoiding EntityFramework and core identity scaffolding code for reasons I can't share here.

Here is the class I wrote

public class CompanyAuthentication
{
    public CompanyAuthentication(AuthenticationStateProvider auth)
    {
        var result = auth.GetAuthenticationStateAsync().Result;
        // here I have access to the current username:
        string username = result.User.Identity.Name;
        // now I can fetch roles from file, but for simplicity, I will use the following:
        if(username.BeginsWith("admin"))
        {
            var claims = new ClaimsIdentity(new Claim[] {new Claim(ClaimType.Role, "admin")});
            result.User.AddIdentity(claims);  // this will have an effect on UI
        }
     
    }
}

I also added the above class as a service in Startup.cs

services.AddScoped<CompanyAuthentication>();

Now, in any razor page, I simply do:

@page "/counter"
@inject CompanyAuthentication auth

<AuthorizeView Roles="admin">
    <Authorized> Welcome admin </Authorized>
    <NotAuthorized> You are not authorized </NotAuthorized>
</AuthorizeView>

That all works fine, as long as I don't forget to inject CompanyAuthentication in each page I intend to use.

Is there a way to automatically inject my class into every page without having to do @inject ?
I am aware that I can write a custom authentication class that inherits AuthenticationStateProvider and then add it as service, but if I do that, I lose access to the currently logged in username, and thus, I can't fetch roles from the database.

I tried to use HttpContext.Current.User.Identity.Name but that is not in the scope of any part in a Balzor server app.

How can I take advantage of Windows AuthenticationStateProvider and at the same time, customize its roles, without having to inject the customization everywhere ?

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

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

发布评论

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

评论(1

平定天下 2025-02-17 03:01:10

您应该能够编写自定义AuthenticationStateProvider。我已经设置了一个将身份验证设置为Windows的Blazor Server网站。

自定义AuthenticationStateProvider。请注意,它从ServerAuthenticationStateProvider继承。

public class MyAuthenticationStateProvider : ServerAuthenticationStateProvider
{
    private bool _isNew = true;

    public async override Task<AuthenticationState> GetAuthenticationStateAsync()
    {
        var state = await base.GetAuthenticationStateAsync();
        // Add your code here to get the user info to use in the logic of what roles you add

        // only add the extra Identity once
        if (_isNew)
            state.User.AddIdentity(AdminIdentity);
        
        _isNew = false;
        return state;
    }

    private ClaimsIdentity AdminIdentity
        => new ClaimsIdentity(new[] { new Claim(ClaimTypes.Role, "admin") }, "My Auth Type");
}

在服务中注册 - 注意订单:

var builder = WebApplication.CreateBuilder(args);

// Add services to the container.

builder.Services.AddAuthentication(NegotiateDefaults.AuthenticationScheme)
   .AddNegotiate();

builder.Services.AddAuthorization(options =>
{
    options.FallbackPolicy = options.DefaultPolicy;
});

builder.Services.AddRazorPages();
builder.Services.AddServerSideBlazor();
// Add custom AuthenticationStateProvider after AddServerSideBlazor will overload the existing registered service
builder.Services.AddScoped<AuthenticationStateProvider, MyAuthenticationStateProvider>();
builder.Services.AddSingleton<WeatherForecastService>();

var app = builder.Build();

这是一个测试页面,可以向您显示主张:

@page "/"
@inject AuthenticationStateProvider Auth;
@using System.Security.Claims
<PageTitle>Index</PageTitle>

<h1>Hello, world!</h1>

Welcome to your new app.

<SurveyPrompt Title="How is Blazor working for you?" />

@if(user is not null)
{
    @foreach(var claim in user.Claims)
    {
        <div>
            @claim.Type : @claim.Value
        </div>
    }
}

@code{
    private ClaimsPrincipal user = default!;

    protected async override Task OnInitializedAsync()
    {
        var state = await Auth.GetAuthenticationStateAsync();
        user = state.User;
    }
}

这是一个屏幕截图,显示了用户Windows安全信息和附加角色。

You should be able to write a custom AuthenticationStateProvider. I've set up a Blazor Server site with authentication set to Windows.

The custom AuthenticationStateProvider. Note it inherits from ServerAuthenticationStateProvider.

public class MyAuthenticationStateProvider : ServerAuthenticationStateProvider
{
    private bool _isNew = true;

    public async override Task<AuthenticationState> GetAuthenticationStateAsync()
    {
        var state = await base.GetAuthenticationStateAsync();
        // Add your code here to get the user info to use in the logic of what roles you add

        // only add the extra Identity once
        if (_isNew)
            state.User.AddIdentity(AdminIdentity);
        
        _isNew = false;
        return state;
    }

    private ClaimsIdentity AdminIdentity
        => new ClaimsIdentity(new[] { new Claim(ClaimTypes.Role, "admin") }, "My Auth Type");
}

Register it in services - note the order:

var builder = WebApplication.CreateBuilder(args);

// Add services to the container.

builder.Services.AddAuthentication(NegotiateDefaults.AuthenticationScheme)
   .AddNegotiate();

builder.Services.AddAuthorization(options =>
{
    options.FallbackPolicy = options.DefaultPolicy;
});

builder.Services.AddRazorPages();
builder.Services.AddServerSideBlazor();
// Add custom AuthenticationStateProvider after AddServerSideBlazor will overload the existing registered service
builder.Services.AddScoped<AuthenticationStateProvider, MyAuthenticationStateProvider>();
builder.Services.AddSingleton<WeatherForecastService>();

var app = builder.Build();

And here's a test page to show you the claims:

@page "/"
@inject AuthenticationStateProvider Auth;
@using System.Security.Claims
<PageTitle>Index</PageTitle>

<h1>Hello, world!</h1>

Welcome to your new app.

<SurveyPrompt Title="How is Blazor working for you?" />

@if(user is not null)
{
    @foreach(var claim in user.Claims)
    {
        <div>
            @claim.Type : @claim.Value
        </div>
    }
}

@code{
    private ClaimsPrincipal user = default!;

    protected async override Task OnInitializedAsync()
    {
        var state = await Auth.GetAuthenticationStateAsync();
        user = state.User;
    }
}

Here's a screen capture showing both the user windows security info and the added Role.

enter image description here

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