Windows 身份验证

您可以通过多种方式在 ASP.NET Core(以及 IdentityServer)中启用 Windows 身份验证。

  • 在 Windows 上使用 IIS 托管(进程内和进程外)

  • 在 Windows 上使用 HTTP.SYS 托管

  • 在任何使用协商身份验证处理程序的平台上(在 ASP.NET Core 3.0 中添加)

注解

我们只有 IIS 托管的文档。 如果您想为文档做出贡献,请打开一个 PR。 谢谢!

在使用 IIS 托管的 Windows 上

当托管在 IIS 中时,典型的 CreateDefaultBuilder 主机设置支持基于 IIS 的 Windows 身份验证。 确保在 launchSettings.json 或您的 IIS 配置中启用了 Windows 身份验证。

IIS 集成层会将 Windows 身份验证处理程序配置到可通过身份验证服务调用的 DI 中。 通常在 IdentityServer 中,建议禁用自动行为。

这是在 ConfigureServices 中完成的(详细信息取决于进程内与进程外托管):

// 配置 IIS 进程外设置(参见 https://github.com/aspnet/AspNetCore/issues/14882)
services.Configure<IISOptions>(iis =>
{
    iis.AuthenticationDisplayName = "Windows";
    iis.AutomaticAuthentication = false;
});

// ..或配置 IIS 进程内设置
services.Configure<IISServerOptions>(iis =>
{
    iis.AuthenticationDisplayName = "Windows";
    iis.AutomaticAuthentication = false;
});

您可以通过在 Windows 方案上调用 ChallengeAsync 来触发 Windows 身份验证(或者如果您想使用常量:Microsoft.AspNetCore.Server.IISIntegration.IISDefaults.AuthenticationScheme)。

这会将 Www-Authenticate 标头发送回浏览器,然后浏览器将重新加载当前的 URL,包括 Windows 身份。 当您在 Windows 方案上调用 AuthenticateAsync 并且返回的主体类型为 WindowsPrincipal 时,您可以判断 Windows 身份验证成功。

主体将具有用户和组 SID 以及 Windows 帐户名称等信息。 以下代码段显示了如何触发身份验证,如果成功,则将信息转换为 temp-Cookie 方法的标准 ClaimsPrincipal:

private async Task<IActionResult> ChallengeWindowsAsync(string returnUrl)
{
    // 查看是否已请求 Windows 身份验证并成功
    var result = await HttpContext.AuthenticateAsync("Windows");
    if (result?.Principal is WindowsPrincipal wp)
    {
        // 我们将发出外部 cookie,
        // 然后将用户重定向回外部回调,
        // 本质上,将 windows auth 视为与任何其他外部身份验证机制相同
        var props = new AuthenticationProperties()
        {
            RedirectUri = Url.Action("Callback"),
            Items =
            {
                { "returnUrl", returnUrl },
                { "scheme", "Windows" },
            }
        };

        var id = new ClaimsIdentity("Windows");

        // sid 是一个很好的子值
        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 auth
        // 因为 windows auth 不支持重定向 uri,
        // 当我们调用 challenge 时会重新触发这个 URL
        return Challenge("Windows");
    }
}