कस्टम दावों के साथ ब्लेज़र विंडोज़ प्रमाणीकरण


सुनिये सब लोग,

मुझे नहीं पता कि मैं इसे पूरी तरह से गलत कर रहा हूं या नहीं, लेकिन मैं जो हासिल करने की कोशिश कर रहा हूं वह है विंडोज़ प्रमाणीकरण और एक अतिरिक्त कस्टमक्लेम के साथ मेरे आईआईएस पर एक ब्लेज़र सर्वर ऐप होस्ट करना ताकि हर किसी को, लेकिन केवल कुछ ही लोगों को एक्सेस करने से रोका जा सके।

अब तक मैंने नीचे चिपकाए गए कोड तक अपना रास्ता बना लिया है, और बात यह है कि यह डिबगिंग के दौरान मेरे विज़ुअल स्टूडियो के साथ काम करता है। वहां सब कुछ अच्छा है और अपेक्षा के अनुरूप काम करता है, लेकिन जैसे ही मैं इसे आईआईएस सर्वर पर प्रकाशित करता हूं तो यह मेरी पहुंच को प्रतिबंधित कर देता है।

अगर कोई मुझे सही दिशा दे सके तो मुझे बहुत खुशी होगी।

अग्रिम में धन्यवाद!

मैंने क्या प्रयास किया है:

उपयोगकर्ताओं को अधिकृत करने के लिए कोड (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 ऑफ़सी पर मैंने इस साइट के लिए WindowsAuth सक्षम किया है और सत्यापित किया है कि नेगोशिएट प्रदाता सूची में शीर्ष पर है।

लेकिन मैं वास्तव में नहीं समझ पाया कि समस्या क्या है, यहां तक ​​कि ChatGpt ने भी मुझे विफल कर दिया… या मैं सही प्रश्न पूछने में विफल रहा।

समाधान 1

वास्तव में क्या करने की आवश्यकता है… एक भाग्यशाली शोध और अपने डिबग को तीन बार जांचने के बाद:

प्रोग्राम.सीएस को एक कस्टम स्कीम-> के साथ एक कस्टम प्रमाणक को इंगित करने की आवश्यकता है

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

समाधान 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 शून्य लौटाता है।

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

コメント

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