[ad_1]
嘿大家,
我不知道我这样做是否完全错误,但我想要实现的是使用 Windows 身份验证在我的 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,并验证了 Negotiate Provider 位于列表顶部。
但我真的不明白问题是什么,即使 ChatGpt 也让我失败……或者我没有提出正确的问题。
解决方案1
实际需要做什么……经过幸运的研究并检查你的调试三次后:
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 { }
解决方案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; } } }
[ad_2]
コメント