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
相关产品推荐
相关产品推荐

