IdentityServer4在IIS上Windows认证失败报401但Visual Studio运行正常
问题描述
我正在尝试使用IdentityServer4(4.0.0版本)实现Windows认证功能,该程序在Visual Studio中运行完全正常,但部署到IIS后,输入凭证后会持续弹出Windows认证窗口,返回401状态码。我还尝试部署了Duende Software的官方示例源码,但也出现了相同的问题,我认为是我这边存在部分配置遗漏,恳请各位帮忙解决。
相关代码
Program.cs
public static IHostBuilder CreateHostBuilder(string[] args) => Host.CreateDefaultBuilder(args) .UseSerilog() .ConfigureWebHostDefaults(webBuilder => { webBuilder.UseStartup<Startup>(); });
launchSettings.json
"windowsAuthentication": true,

ExternalController.cs
public async Task<IActionResult> Challenge(string scheme, string returnUrl) { if (string.IsNullOrEmpty(returnUrl)) returnUrl = "~/"; if(scheme == "Windows") { return await ChallengeWindowsAsync(returnUrl); } // 验证returnUrl:要么是合法的OIDC URL,要么是本地页面地址 if (Url.IsLocalUrl(returnUrl) == false && _interaction.IsValidReturnUrl(returnUrl) == false) { // 用户可能点击了恶意链接,需记录日志 throw new Exception("invalid return URL"); } // 启动认证挑战,将return URL和scheme带回 var props = new AuthenticationProperties { RedirectUri = Url.Action(nameof(Callback)), Items = { { "returnUrl", returnUrl }, { "scheme", scheme }, } }; return Challenge(props, scheme); } //ChallengeWindowsAsync方法 private async Task<IActionResult> ChallengeWindowsAsync(string returnUrl) { // 检查Windows认证是否已请求并验证通过 var result = await HttpContext.AuthenticateAsync("Windows"); if (result?.Principal is WindowsPrincipal wp) { // 我们将颁发外部Cookie,然后将用户重定向回外部回调,本质上将Windows认证视为与其他外部认证机制相同 var props = new AuthenticationProperties() { RedirectUri = Url.Action("Callback"), Items = { { "returnUrl", returnUrl }, { "scheme", "Windows" }, } }; var id = new ClaimsIdentity("Windows"); // sid是sub声明的优质取值 id.AddClaim(new Claim(JwtClaimTypes.Subject, wp.FindFirst(ClaimTypes.PrimarySid).Value)); // 账户名是最接近展示名的字段 id.AddClaim(new Claim(JwtClaimTypes.Name, wp.Identity.Name)); // 将组作为声明添加——如果组数量过多请谨慎操作 var wi = wp.Identity as WindowsIdentity; // 将组SID转换为展示名 var groups = wi.Groups.Translate(typeof(NTAccount)); var roles = groups.Select(x => new Claim(JwtClaimTypes.Role, x.Value)); id.AddClaims(roles); await HttpContext.SignInAsync( IdentityServerConstants.ExternalCookieAuthenticationScheme, new ClaimsPrincipal(id), props); return Redirect(props.RedirectUri); } else { // 触发Windows认证 // 由于Windows认证不支持redirect uri,调用挑战时会重新触发此URL return Challenge("Windows"); } }
IIS配置情况
已开启Windows authentication

解决方案
按优先级依次排查以下配置项:
- 首先确认IIS站点的匿名认证必须和Windows认证同时开启。IdentityServer的大部分端点需要匿名访问,只有Windows挑战的接口需要走Windows认证,如果关闭匿名会导致所有请求都触发Windows校验,出现反复弹框的问题。
- 检查站点应用程序池的.NET CLR版本是否设置为无托管代码,托管管道模式设置为集成。
- 确认部署后站点根目录的web.config已经自动生成了正确的认证配置,需包含以下节点:
<system.webServer> <security> <authentication> <windowsAuthentication enabled="true" /> <anonymousAuthentication enabled="true" /> </authentication> </security> <aspNetCore processPath=".\你的程序名.exe" stdoutLogEnabled="false" stdoutLogFile=".\logs\stdout" hostingModel="inprocess" /> </system.webServer>
注意必须使用inprocess托管模型,OutOfProcess模式下Windows认证无法正常传递身份信息到ASP.NET Core程序。
- 如果你是用域名访问站点,需要在客户端的Internet选项->本地Intranet->站点->高级里,把你的站点域名加入到本地Intranet区域,避免Windows认证默认不传递当前登录用户凭证到非内网站点。
- 检查IIS的Windows认证提供程序顺序,把
NTLM调到Negotiate前面,部分域环境下Kerberos配置不全会导致Negotiate认证失败,降级用NTLM即可正常工作。
内容的提问来源于stack exchange,提问作者leo
相关产品推荐
相关产品推荐

