【解決方法】カスタム クレームを使用した Blazor Windows 認証

プログラミングQA


こんにちは、みなさん、

私が完全に間違っているのかどうかはわかりませんが、私が達成しようとしているのは、Windows 認証と追加のcustomClaimを使用してIISでBlazorサーバーアプリをホストし、誰もがアクセスできないようにすることですが、ほんの一握りの人だけです。

これまでのところ、以下に貼り付けたコードまで進みましたが、デバッグ中にビジュアルスタジオで動作するということです。 ここではすべて問題なく、期待どおりにジョブを実行しますが、IIS サーバーに公開するとすぐにアクセスが制限されます。

誰かが私を正しい方向に導いてくれたら、私はとても幸せになるでしょう。

前もって感謝します!

私が試したこと:

ユーザーを認証するコード (program.cs)

using System.Security.Claims;
using System.Security.Principal;
using ImsServerMonitor.Data;
using Microsoft.AspNetCore.Authentication.Negotiate;

var builder = WebApplication.CreateBuilder(args);

// Add services to the container.
builder.Services.AddAuthentication(NegotiateDefaults.AuthenticationScheme)
    .AddNegotiate(options =>
    {
        options.Events = new NegotiateEvents
        {
            OnAuthenticated = context =>
            {
                if (context.Principal.Identity is WindowsIdentity windowsIdentity)
                {
                    string loginName = windowsIdentity.Name;
                    
                    if (loginName.Contains("User1")
                        || loginName.Contains("User2")
                        || loginName.Contains("User3")
                        || loginName.Contains("User4"))
                    {
                        var claims = new List<Claim>
                        {
                            new Claim("CustomClaim", "Admin")
                        };

                        context.Principal.AddIdentity(new ClaimsIdentity(claims));
                    }
                }

                return Task.CompletedTask;
            }
        };
    });
builder.Services.AddAuthorization(options =>
{
    options.AddPolicy("AdminOnly", policyBuilder => policyBuilder.RequireClaim("CustomClaim", "Admin"));
    // By default, all incoming requests will be authorized according to the default policy.
    //options.FallbackPolicy = options.DefaultPolicy;
    options.FallbackPolicy = options.GetPolicy("AdminOnly");
});

builder.Services.AddRazorPages();
builder.Services.AddServerSideBlazor();
builder.Services.AddSingleton<MonitorEngine>();
builder.Services.AddDevExpressBlazor();

var app = builder.Build();

// Configure the HTTP request pipeline.
if (!app.Environment.IsDevelopment())
{
    app.UseExceptionHandler("/Error");
    // The default HSTS value is 30 days. You may want to change this for production scenarios, see https://aka.ms/aspnetcore-hsts.
    app.UseHsts();
}

app.UseHttpsRedirection();

app.UseStaticFiles();

app.UseRouting();

app.UseAuthentication();
app.UseAuthorization();

app.MapControllers();
app.MapBlazorHub();
app.MapFallbackToPage("/_Host");

app.Run();

さらに、IIS ofc では、このサイトに対して WindowsAuth が有効になっており、ネゴシエート プロバイダーがリストの先頭にあることを確認しました。

しかし、問題が何なのか本当にわかりません。ChatGpt でも失敗しました…または、正しい質問をすることができませんでした。

解決策 4

この質問と解決策をありがとうございます。 よく働く。 私は .NET 8 を使用していますが、以下のコードに 1 つの小さな変更を加える必要がありました。

var principal = new ClaimsPrincipal(identity);
var ticket = new AuthenticationTicket(principal, Scheme.Name);
return AuthenticateResult.Success(ticket);

Context.User.AddIdentity(identity);
var ticket = new AuthenticationTicket(Context.User, Scheme.Name);
return AuthenticateResult.Success(ticket);

そうしないと、コード内の他の場所でユーザー名にアクセスできなくなります。
以下のコードでは、元のコードを使用すると _authMessage は null を返します。

@code {
    [CascadingParameter]
    private Task<AuthenticationState>? AuthenticationState { get; set; }

    protected override async Task OnInitializedAsync()
    {
        if (AuthenticationState is not null)
        {
            var authState = await AuthenticationState;
            var user = authState.User;

            if (user?.Identity is not null && user.Identity.IsAuthenticated)
            {
                _authMessage = user.Identity.Name;
            }
        }
    }

解決策 1

実際に行う必要があったのは…幸運な調査とデバッグの 3 回のチェックの後です。

Program.cs は、カスタム スキームを持つカスタム認証子を指す必要があります->

builder.Services.AddAuthentication(options =>
{
    options.DefaultScheme = "CustomWindowsAuthentication";
}).AddScheme<CustomWindowsAuthenticationOptions, CustomWindowsAuthenticationHandler>("CustomWindowsAuthentication", null);

その場合、そのようなものを処理する追加のクラスが実際に必要になります。

public class CustomWindowsAuthenticationHandler : AuthenticationHandler<CustomWindowsAuthenticationOptions>
    {
        public CustomWindowsAuthenticationHandler(
            IOptionsMonitor<CustomWindowsAuthenticationOptions> options,
            ILoggerFactory logger,
            UrlEncoder encoder,
            ISystemClock clock)
            : base(options, logger, encoder, clock)
        {
        }

        protected override async Task<AuthenticateResult> HandleAuthenticateAsync()
        {
            if (!Context.User.Identity.IsAuthenticated || !(Context.User.Identity is WindowsIdentity windowsIdentity))
            {
                return AuthenticateResult.NoResult();
            }

            var loginName = windowsIdentity.Name;
            if (loginName.Contains("User1")
                || loginName.Contains("User2")
                || loginName.Contains("User3")
                || loginName.Contains("User4"))
            {
                var claims = new List<Claim>
                {
                    new Claim("CustomClaim", "Admin")
                };

                var identity = new ClaimsIdentity(claims, Scheme.Name);
                var principal = new ClaimsPrincipal(identity);

                var ticket = new AuthenticationTicket(principal, Scheme.Name);
                return AuthenticateResult.Success(ticket);
            }

            return AuthenticateResult.Fail("Custom authentication failed.");
        }
    }

そして完全を期すために、「CustomWindowsAuthenticationOptions」も必要です。ただし、特別なオプションは必要ないため空になっています。

public class CustomWindowsAuthenticationOptions : AuthenticationSchemeOptions
    {
        
    }

コメント

タイトルとURLをコピーしました