You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

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

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.10.12 03:39:01