ASP.NET Core扩展现有AuthenticationScheme的优选实现方案咨询
你完全可以通过继承NegotiateHandler实现自定义认证逻辑,无需额外中间件,以下是完整可落地的实现方案:
1. 实现自定义认证处理器
继承原生NegotiateHandler重写认证逻辑,内置Windows认证+AD用户校验+自定义Claim添加逻辑:
using Microsoft.AspNetCore.Authentication; using Microsoft.AspNetCore.Authentication.Negotiate; using Microsoft.Extensions.Logging; using Microsoft.Extensions.Options; using System.Security.Claims; using System.Security.Principal.Windows; using System.Text.Encodings.Web; public class MyCustomNegotiateHandler : NegotiateHandler { private readonly IServiceScopeFactory _serviceScopeFactory; // 自定义认证方案名称常量 public const string SchemeName = "CustomNegotiate"; public MyCustomNegotiateHandler( IOptionsMonitor<NegotiateOptions> options, ILoggerFactory logger, UrlEncoder encoder, ISystemClock clock, IServiceScopeFactory serviceScopeFactory) : base(options, logger, encoder, clock) { _serviceScopeFactory = serviceScopeFactory; } protected override async Task<AuthenticateResult> HandleAuthenticateAsync() { // 执行原生Windows认证逻辑 var baseAuthResult = await base.HandleAuthenticateAsync(); if (!baseAuthResult.Succeeded) { return baseAuthResult; } // 获取AD用户名 var windowsIdentity = baseAuthResult.Principal.Identity as WindowsIdentity; var adUserName = windowsIdentity?.Name; if (string.IsNullOrWhiteSpace(adUserName)) { return AuthenticateResult.Fail("无法获取有效AD用户信息"); } // 从独立服务作用域获取用户查询服务,避免单例处理器访问作用域服务报错 using var scope = _serviceScopeFactory.CreateScope(); var userService = scope.ServiceProvider.GetRequiredService<IYourUserQueryService>(); // 校验AD用户是否在系统白名单中,获取内部ID var internalUserId = await userService.GetInternalUserIdByAdName(adUserName); if (internalUserId == null) { return AuthenticateResult.Fail("用户无系统访问权限"); } // 追加内部ID到Claim集合 var additionalClaims = new List<Claim> { new Claim("InternalUserId", internalUserId.ToString()) }; var combinedIdentity = new ClaimsIdentity(windowsIdentity, additionalClaims); var combinedPrincipal = new ClaimsPrincipal(combinedIdentity); return AuthenticateResult.Success(new AuthenticationTicket(combinedPrincipal, Scheme.Name)); } }
注意:代码中的
IYourUserQueryService替换为你自己的用户数据查询服务,实现AD用户名查内部ID的逻辑即可。
2. 实现认证方案注册扩展方法
封装扩展方法实现你需要的链式调用语法:
public static class CustomNegotiateAuthenticationExtensions { public static AuthenticationBuilder AddCustomNegotiate( this AuthenticationBuilder builder, Action<NegotiateOptions>? configureOptions = null) { return builder.AddScheme<NegotiateOptions, MyCustomNegotiateHandler>( MyCustomNegotiateHandler.SchemeName, configureOptions); } }
3. 注册使用
直接在服务注册时使用即可,完全符合你期望的调用方式:
// 注册自定义认证方案 services.AddAuthentication(MyCustomNegotiateHandler.SchemeName) .AddCustomNegotiate(); // 你的其他服务注册逻辑,比如你的IYourUserQueryService实现、DbContext等 services.AddScoped<IYourUserQueryService, YourUserQueryServiceImpl>();
请求管道中不需要额外加自定义中间件,只需要保留原生的认证、授权中间件即可:
app.UseRouting(); app.UseAuthentication(); // 仅需调用原生认证中间件 app.UseAuthorization(); app.MapControllers();
其他说明
- 若需要调整Windows认证的原生配置,可直接在
AddCustomNegotiate的委托参数中修改NegotiateOptions,和原生AddNegotiate用法完全一致 - 自定义Claim的类型可以根据业务需要修改,建议定义为全局常量避免后续取值出错
- 可以根据业务需要追加更多自定义Claim,只需在上面的
additionalClaims集合中添加即可
内容的提问来源于stack exchange,提问作者Beltway
相关产品推荐
相关产品推荐

