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

IIS中启用匿名认证导致ASP.NET Core应用Windows认证中间件失效的配置求助

IIS中启用匿名认证导致ASP.NET Core应用Windows认证中间件失效的配置求助

问题描述

我在ASP.NET Core应用中添加了自定义认证中间件,逻辑是优先尝试JWT认证,失败或不存在时再尝试Windows认证:

app.Use(async (context, next) => 
{ 
    var authService = context.RequestServices.GetRequiredService<IAuthenticationService>(); 
    AuthenticateResult result = null; 

    // 先尝试JWT认证
    if (context.Request.Headers.ContainsKey("Authorization")) 
    { 
        result = await authService.AuthenticateAsync(context, JwtBearerDefaults.AuthenticationScheme); 
    } 

    // JWT失败或未提供时,尝试Windows认证
    if (result == null || !result.Succeeded) 
    { 
        result = await authService.AuthenticateAsync(context, NegotiateDefaults.AuthenticationScheme); 
    } 

    if (result?.Succeeded == true) 
    { 
        context.User = result.Principal!; 
    } 

    await next(); 
});

同时配置了认证服务:

services.AddAuthentication( options => 
{ 
    options.DefaultAuthenticateScheme = NegotiateDefaults.AuthenticationScheme; 
}) 
.AddNegotiate() 
.AddJwtBearer(JwtBearerDefaults.AuthenticationScheme, options => 
{ 
    options.TokenValidationParameters = new TokenValidationParameters 
    { 
        ValidateIssuer = true, 
        ValidateAudience = true, 
        ValidateLifetime = true, 
        ValidateIssuerSigningKey = true, 
        ValidIssuer = Configuration.GetValue<string>("TokenValidIssuer"), 
        ValidAudience = Configuration.GetValue<string>("TokenValidAudience"), 
        IssuerSigningKey = new SymmetricSecurityKey(Encoding.UTF8.GetBytes(Configuration.GetValue<string>("SuperSecretKey"))) 
    }; 
});

应用部署在IIS上,当我同时启用匿名认证和Windows认证时,中间件里的Windows认证就失效了,result始终显示未认证成功。想请教下该如何配置IIS和应用?


解决方案建议

1. 确保web.config正确配置Windows认证转发

在项目的web.config中,需要明确开启Windows认证转发,让IIS把客户端的Windows凭证传递给ASP.NET Core应用:

<configuration>
  <system.webServer>
    <security>
      <authentication>
        <anonymousAuthentication enabled="true" />
        <windowsAuthentication enabled="true" />
      </authentication>
    </security>
    <aspNetCore processPath="dotnet" arguments=".\YourApp.dll" 
                stdoutLogEnabled="false" stdoutLogFile=".\logs\stdout" 
                hostingModel="inprocess" 
                forwardWindowsAuthToken="true" />
  </system.webServer>
</configuration>

重点是forwardWindowsAuthToken="true",这个配置会让IIS将Windows认证的令牌转发给后端的ASP.NET Core进程。

2. 优化自定义中间件的逻辑

当IIS允许匿名认证时,客户端不会自动发送Windows凭证,所以直接调用AuthenticateAsync可能无法获取到有效结果。你需要在JWT认证失败后,手动触发Windows认证的挑战,再尝试获取认证结果:

app.Use(async (context, next) => 
{ 
    var authService = context.RequestServices.GetRequiredService<IAuthenticationService>(); 
    AuthenticateResult result = null; 

    // 先尝试JWT认证
    if (context.Request.Headers.ContainsKey("Authorization")) 
    { 
        result = await authService.AuthenticateAsync(context, JwtBearerDefaults.AuthenticationScheme); 
    } 

    // JWT失败或未提供时,尝试Windows认证
    if (result == null || !result.Succeeded) 
    {
        // 触发Windows认证挑战,让客户端发送凭证
        await authService.ChallengeAsync(context, NegotiateDefaults.AuthenticationScheme);
        // 再次尝试认证
        result = await authService.AuthenticateAsync(context, NegotiateDefaults.AuthenticationScheme);
    } 

    if (result?.Succeeded == true) 
    { 
        context.User = result.Principal!; 
    } 

    await next(); 
});

注意:如果是API场景,触发挑战可能会返回401并携带WWW-Authenticate头部,客户端需要支持协商认证(比如浏览器会自动弹出登录框,或者客户端主动发送凭证)。

3. 检查IIS的Windows认证细节设置

  • 打开IIS站点的Windows认证功能,点击右侧的高级设置:
    • 确保启用内核模式认证处于勾选状态(默认是勾选的,但如果被修改过需要确认);
    • 扩展保护设置为接受或关闭(如果是内部局域网环境,关闭扩展保护可能更容易兼容)。
  • 确认应用池的托管管道模式为集成(ASP.NET Core应用必须使用集成模式);
  • 应用池的身份如果使用ApplicationPoolIdentity,需要确保该账户对应用文件目录有读取权限,并且如果需要域内认证,应用池身份需要有对应的权限。

4. 调整认证服务的默认配置

虽然你自定义了中间件,但可以调整AddAuthentication的配置,确保Negotiate认证能正确处理:

services.AddAuthentication()
    .AddNegotiate(options =>
    {
        options.Events = new NegotiateEvents
        {
            OnAuthenticationFailed = context =>
            {
                // 这里可以添加日志,排查认证失败的具体原因
                // 比如记录context.Exception的详细信息
                return Task.CompletedTask;
            }
        };
    })
    .AddJwtBearer(JwtBearerDefaults.AuthenticationScheme, options => 
    { 
        // 保持原有的JWT配置
        options.TokenValidationParameters = new TokenValidationParameters 
        { 
            ValidateIssuer = true, 
            ValidateAudience = true, 
            ValidateLifetime = true, 
            ValidateIssuerSigningKey = true, 
            ValidIssuer = Configuration.GetValue<string>("TokenValidIssuer"), 
            ValidAudience = Configuration.GetValue<string>("TokenValidAudience"), 
            IssuerSigningKey = new SymmetricSecurityKey(Encoding.UTF8.GetBytes(Configuration.GetValue<string>("SuperSecretKey"))) 
        }; 
    });

这里移除了DefaultAuthenticateScheme的设置,因为你的自定义中间件已经手动处理了认证顺序,避免默认配置和自定义逻辑冲突。


内容来源于stack exchange

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.04.08 10:33:03