在 ASP.NET Core 中配置 Windows 身份验证

作者:Rick AndersonKirk Larkin

可以为由 IISKestrelHTTP.sys 托管的 ASP.NET Core 应用配置 Windows 身份验证(也称为 Negotiate、Kerberos 或 NTLM 身份验证)。

Windows 身份验证依赖于操作系统对 ASP.NET Core 应用进行身份验证。 Windows 身份验证用于在公司网络上运行的服务器,该公司网络使用 Active Directory 域标识或 Windows 帐户来标识用户。 Windows 身份验证最适合用户、客户端应用和 Web 服务器属于同一 Windows 域的 Intranet 环境。

注意

Windows 身份验证不支持 HTTP/2。 身份验证质询可通过 HTTP/2 响应发送,但客户端必须在进行身份验证之前降级到 HTTP/1.1。

代理和负载均衡器方案

Windows 身份验证是一种有状态方案,主要用于 Intranet,其中的代理或负载均衡器通常不处理客户端和服务器之间流量的情况。 如果使用了代理或负载均衡器,则仅当代理或负载均衡器符合以下情况时 Windows 身份验证才起作用:

  • 处理身份验证。
  • 将用户身份验证信息传递给应用(例如,在请求头中),应用根据身份验证信息执行操作。

在使用代理和负载平衡器的环境中,Windows 身份验证的另一种选择是结合使用 Active Directory 联合服务 (ADFS) 和 OpenID Connect (OIDC)。

IIS/IIS Express

Program.cs中调用AddAuthentication以添加 NuGet 包Microsoft.AspNetCore.Authentication.Negotiate和身份验证服务:

using Microsoft.AspNetCore.Authentication.Negotiate;

var builder = WebApplication.CreateBuilder(args);

builder.Services.AddAuthentication(NegotiateDefaults.AuthenticationScheme)
   .AddNegotiate();

builder.Services.AddAuthorization(options =>
{
    options.FallbackPolicy = options.DefaultPolicy;
});
builder.Services.AddRazorPages();

var app = builder.Build();
if (!app.Environment.IsDevelopment())
{
    app.UseExceptionHandler("/Error");
    app.UseHsts();
}

app.UseHttpsRedirection();
app.UseStaticFiles();

app.UseRouting();

app.UseAuthentication();
app.UseAuthorization();

app.MapRazorPages();

app.Run();

上述代码由指定了 Windows 身份验证的 ASP.NET Core Razor Pages 模板生成。

启动设置(调试程序)

启动设置的配置只会影响 IIS Express 的Properties/launchSettings.json文件,而不会为 Windows 身份验证配置 IIS。 IIS 部分介绍了服务器配置。

通过 Visual Studio 或 .NET Core CLI 提供的Web 应用程序模板可以配置为支持 Windows 身份验证,它会自动更新Properties/launchSettings.json文件。

新建项目

创建新的 Razor Pages 或 MVC 应用。 在“其他信息”对话框中,将“身份验证类型”设置为“Windows”。

运行应用。 用户名显示在呈现的应用用户界面中。

现有项目

项目的属性会启用 Windows 身份验证并禁用匿名身份验证。 打开“启动配置文件”对话框:

  1. 在“解决方案资源管理器”中,右键单击项目,然后选择“属性”。
  2. 转到“调试”>“常规”选项卡,然后选择“打开调试启动配置文件 UI”>
  3. 清除“启用匿名身份验证”复选框。
  4. 选择“启用 Windows 身份验证”复选框。

或者,可以在launchSettings.json文件的iisSettings节点中配置属性:

"iisSettings": {
    "windowsAuthentication": true,
    "anonymousAuthentication": false,
    "iisExpress": {
        "applicationUrl": "http://localhost:52171/",
        "sslPort": 44308
    }
}

IIS

IIS 使用 ASP.NET Core 模块来托管 ASP.NET Core 应用。 通过 web.config 文件为 IIS 配置 Windows 身份验证。 以下部分介绍如何执行这些操作:

  • 提供一个本地 web.config 文件,该文件在部署应用时在服务器上激活 Windows 身份验证。
  • 使用 IIS 管理器配置已部署到服务器的 ASP.NET Core 应用的 web.config文件。

如果尚未这样做,请启用 IIS 来托管 ASP.NET Core 应用。 有关详细信息,请参阅 使用 IIS 在 Windows 上托管 ASP.NET Core

启用 IIS 角色服务进行 Windows 身份验证。 有关详细信息,请参阅在 IIS 角色服务中启用 Windows 身份验证(请参阅步骤 2)

IIS 集成中间件默认配置为自动对请求进行身份验证。 有关详细信息,请参阅使用 IIS 在 Windows 上托管 ASP.NET Core:IIS 选项 (AutomaticAuthentication)

默认情况下,ASP.NET Core 模块配置为将 Windows 身份验证令牌转发到应用。 有关详细信息,请参阅 ASP.NET Core 模块配置参考:aspNetCore 元素的属性

请使用下述任一方法:

  • 在发布和部署项目之前,请将以下 web.config 文件添加到项目根目录:

    <?xml version="1.0" encoding="utf-8"?>
    <configuration>
      <location path="." inheritInChildApplications="false">
        <system.webServer>
          <security>
            <authentication>
              <anonymousAuthentication enabled="false" />
              <windowsAuthentication enabled="true" />
            </authentication>
          </security>
        </system.webServer>
      </location>
    </configuration>
    

    如果项目是由 .NET Core SDK 发布的,(项目文件中的 <IsTransformWebConfigDisabled> 属性未设置为 true),则发布的 web.config 文件中包含 <location><system.webServer><security><authentication> 部分。 有关 <IsTransformWebConfigDisabled> 属性的详细信息,请参阅使用 IIS 在 Windows 上托管 ASP.NET Core

  • 发布和部署项目后,请使用 IIS 管理器执行服务器端配置:

    1. 在 IIS 管理器中,选择“连接”侧栏的“站点”节点下的 IIS 站点。
    2. 双击“IIS”区域中的“身份验证”。
    3. 选择“匿名身份验证”。 选择“操作”侧栏中的“禁用”。
    4. 选择 “Windows 身份验证” 。 选择“操作”侧栏中的“启用”。

    执行这些操作时,IIS 管理器会修改应用的 web.config 文件。 添加了一个 <system.webServer><security><authentication> 节点,其中包含 anonymousAuthenticationwindowsAuthentication 的更新设置:

    <system.webServer>
      <security>
        <authentication>
          <anonymousAuthentication enabled="false" />
          <windowsAuthentication enabled="true" />
        </authentication>
      </security>
    </system.webServer>
    

    IIS 管理器添加到 web.config 文件的 <system.webServer> 部分位于发布应用时 .NET Core SDK 添加的应用的 <location> 部分之外。 由于该部分是在 <location> 节点之外添加的,因此设置会被任何子应用继承到当前应用。 若要防止继承,请将添加的 <security> 部分移动到 .NET Core SDK 提供的 <location><system.webServer> 部分内。

    当使用 IIS 管理器添加 IIS 配置时,它只会影响该应用在服务器上的 web.config 文件。 如果服务器的 web.config 副本替换为项目的 web.config 文件,则应用的后续部署可能会覆盖服务器上的设置。 使用以下任一方法管理设置:

    • 在部署时覆盖文件后,使用 IIS 管理器重置 web.config 文件中的设置。
    • 使用设置在本地将 web.config 文件添加到应用。

Kestrel

Microsoft.AspNetCore.Authentication.Negotiate NuGet 包可与 Kestrel 结合使用,以支持在 Windows、Linux 和 macOS 上使用 Negotiate 和 Kerberos 进行 Windows 身份验证。

警告

凭据可以跨连接上的请求持久保存。 Negotiate 身份验证不能与代理一起使用,除非代理与 Kestrel 保持 1:1 的连接关联(持久连接)。

注意

Negotiate 处理程序检测基础服务器是否本机支持 Windows 身份验证,以及是否启用了该身份验证。 如果服务器支持 Windows 身份验证但其已被禁用,则会引发错误,要求启用服务器实现。 若在服务器中启用了 Windows 身份验证,Negotiate 处理程序会以透明方式将身份验证请求转发到该服务器。

通过以下突出显示的Program.cs代码启用身份验证:

using Microsoft.AspNetCore.Authentication.Negotiate;

var builder = WebApplication.CreateBuilder(args);

builder.Services.AddAuthentication(NegotiateDefaults.AuthenticationScheme)
   .AddNegotiate();

builder.Services.AddAuthorization(options =>
{
    options.FallbackPolicy = options.DefaultPolicy;
});
builder.Services.AddRazorPages();

var app = builder.Build();
if (!app.Environment.IsDevelopment())
{
    app.UseExceptionHandler("/Error");
    app.UseHsts();
}

app.UseHttpsRedirection();
app.UseStaticFiles();

app.UseRouting();

app.UseAuthentication();
app.UseAuthorization();

app.MapRazorPages();

app.Run();

上述代码由指定了 Windows 身份验证的 ASP.NET Core Razor Pages 模板生成。 上面的代码使用了以下 API:

Kerberos 身份验证和基于角色的访问控制 (RBAC)

Linux 或 macOS 上的 Kerberos 身份验证不为经过身份验证的用户提供任何角色信息。 若要向 Kerberos 用户添加角色和组信息,必须将身份验证处理程序配置为从 LDAP 域中检索角色。 最基本的配置仅指定要查询的 LDAP 域,并使用经过身份验证的用户上下文来查询 LDAP 域:

using Microsoft.AspNetCore.Authentication.Negotiate;
using System.Runtime.InteropServices;

var builder = WebApplication.CreateBuilder(args);

builder.Services.AddAuthentication(NegotiateDefaults.AuthenticationScheme)
    .AddNegotiate(options =>
    {
        if (RuntimeInformation.IsOSPlatform(OSPlatform.Linux))
        {
            options.EnableLdap("contoso.com");
        }
    });

某些配置可能要求提供特定凭据才可查询 LDAP 域。 可以在以下突出显示的选项中指定凭据:

using Microsoft.AspNetCore.Authentication.Negotiate;
using System.Runtime.InteropServices;

var builder = WebApplication.CreateBuilder(args);

builder.Services.AddAuthentication(NegotiateDefaults.AuthenticationScheme)
        .AddNegotiate(options =>
        {
            if (RuntimeInformation.IsOSPlatform(OSPlatform.Linux))
            {
                options.EnableLdap(settings =>
                {
                    settings.Domain = "contoso.com";
                    settings.MachineAccountName = "machineName";
                    settings.MachineAccountPassword =
                                      builder.Configuration["Password"];
                });
            }
        });

builder.Services.AddRazorPages();

默认情况下,Negotiate 身份验证处理程序会解析嵌套域。 在大型或复杂 LDAP 环境中,解析嵌套域可能会导致查找速度缓慢或每个用户使用大量内存。 可以使用 IgnoreNestedGroups 选项来禁用嵌套域解析。

允许匿名请求。 使用 ASP.NET Core 授权质询匿名身份验证请求。

Windows 环境配置

Microsoft.AspNetCore.Authentication.Negotiate 组件执行用户模式身份验证。 必须将服务主体名称 (SPN) 添加到运行服务的用户帐户,而不是计算机帐户。 在管理命令外壳中执行 setspn -S HTTP/myservername.mydomain.com myuser

Kerberos 与 NTLM

适用于 ASP.NET Core 的Kestrel上的协商包尝试使用 Kerberos,这是一种比NTLM更安全、更快速的身份验证方案:

using Microsoft.AspNetCore.Authentication.Negotiate;

var builder = WebApplication.CreateBuilder(args);

builder.Services.AddAuthentication(NegotiateDefaults.AuthenticationScheme)
   .AddNegotiate();

builder.Services.AddAuthorization(options =>
{
    options.FallbackPolicy = options.DefaultPolicy;
});
builder.Services.AddRazorPages();

var app = builder.Build();

NegotiateDefaults.AuthenticationScheme指定 Kerberos,因为它是默认值。

IIS、IISExpress 和Kestrel都支持 Kerberos 和NTLM

将 IIS 或 IISExpress 和 Fiddler 等工具结合使用,以检查WWW-Authenticate:显示Negotiate或 NTLM。

Kestrel仅显示WWW-Authenticate: Negotiate

WWW-Authenticate: Negotiate标头表示服务器可以使用 NTLM 或 Kerberos。 Kestrel需要Negotiate标头前缀,它不支持在请求或响应身份验证标头中直接指定NTLM。 NTLM 在Kestrel中受支持,但必须将其作为Negotiate发送。

在Kestrel上,要查看是否使用了 NTLM 或 Kerberos,请对标头进行 Base64 解码,它会显示NTLMHTTPHTTP指示使用了 Kerberos。

Linux 和 macOS 环境配置

有关将 Linux 或 macOS 计算机加入到 Windows 域的说明,请参阅使用 Windows 身份验证 Kerberos 将 Azure Data Studio 连接到 SQL Server 一文。 可按照该说明为域中的 Linux 计算机创建计算机帐户。 必须将 SPN 添加到该计算机帐户。

注意

按照使用 Windows 身份验证 Kerberos 将 Azure Data Studio 连接到 SQL Server 一文中的指南操作时,可根据需要将 python-software-properties 替换为 python3-software-properties

将 Linux 或 macOS 计算机加入域后,还需要执行其他步骤才可使用 SPN 提供 keytab 文件

  • 在域控制器上,向计算机帐户添加新的 Web 服务 SPN:
    • setspn -S HTTP/mywebservice.mydomain.com mymachine
    • setspn -S HTTP/mywebservice@MYDOMAIN.COM mymachine
  • 使用 ktpass 生成 keytab 文件:
    • ktpass -princ HTTP/mywebservice.mydomain.com@MYDOMAIN.COM -pass myKeyTabFilePassword -mapuser MYDOMAIN\mymachine$ -pType KRB5_NT_PRINCIPAL -out c:\temp\mymachine.HTTP.keytab -crypto AES256-SHA1
    • 某些字段必须按照指示以大写字母指定。
  • 将 keytab 文件复制到 Linux 或 macOS 计算机。
  • 通过环境变量选择 keytab 文件:export KRB5_KTNAME=/tmp/mymachine.HTTP.keytab
  • 调用 klist 以显示当前可用的 SPN。

注意

keytab 文件包含域访问凭据并且必须受到相应保护。

HTTP.sys

HTTP.sys 支持使用 Negotiate、NTLM 或基本身份验证进行内核模式 Windows 身份验证。

下面的代码添加身份验证,并将应用的 Web 主机配置为将 HTTP.sys 用于 Windows 身份验证:

using Microsoft.AspNetCore.Server.HttpSys;
using System.Runtime.InteropServices;

var builder = WebApplication.CreateBuilder(args);

builder.Services.AddAuthentication(HttpSysDefaults.AuthenticationScheme);

if (RuntimeInformation.IsOSPlatform(OSPlatform.Windows))
{
    builder.WebHost.UseHttpSys(options =>
        {
            options.Authentication.Schemes =
                AuthenticationSchemes.NTLM |
                AuthenticationSchemes.Negotiate;
            options.Authentication.AllowAnonymous = false;
        });
}

注意

HTTP.sys 通过 Kerberos 身份验证协议委托给内核模式身份验证。 Kerberos 和 HTTP.sys 不支持用户模式身份验证。 必须使用计算机帐户来解密从 Active Directory 获取的并由客户端转发到服务器的 Kerberos 令牌/票证,以便对用户进行身份验证。 注册主机的服务主体名称 (SPN),而不是应用的用户。

注意

Nano Server 版本 1709 或更高版本不支持 HTTP.sys。 若要将 Windows 身份验证和 HTTP.sys 用于 Nano Server,请使用 Server Core (microsoft/windowsservercore) 容器。 有关 Server Core 的详细信息,请参阅什么是 Windows Server 中的 Server Core 安装选项?

对用户授权

匿名访问的配置状态决定了在应用中使用 [Authorize][AllowAnonymous] 属性的方式。 以下两部分说明了如何处理不允许和允许的匿名访问配置状态。

不允许匿名访问

如果启用 Windows 身份验证并禁用匿名访问,则 [[Authorize]](xref:Microsoft.AspNetCore.Authorization.AuthorizeAttribute) 和 [AllowAnonymous] 属性无效。 如果将 IIS 站点配置为不允许匿名访问,则请求永远不会到达应用。 因此,[AllowAnonymous] 属性不适用。

允许匿名访问

如果启用了 Windows 身份验证和匿名访问,可使用 [[Authorize]](xref:Microsoft.AspNetCore.Authorization.AuthorizeAttribute) 和 [AllowAnonymous] 属性。 利用 [[Authorize]](xref:Microsoft.AspNetCore.Authorization.AuthorizeAttribute) 属性,可以保护需要进行身份验证的应用的终结点。 [AllowAnonymous] 属性替代允许匿名访问的应用中的 [Authorize] 属性。 有关属性用法的详细信息,请参阅 ASP.NET Core 中的简单授权

注意

默认情况下,无权访问页面的用户会看到一个空 HTTP 403 响应。 可以将 StatusCodePages 中间件配置为向用户提供更好的“拒绝访问”体验。

模拟

ASP.NET Core 不实现模拟。 应用使用应用池或进程标识,使用应用的标识运行所有请求。 如果应用应代表用户执行操作,请在Program.cs终端内联中间件中使用WindowsIdentity.RunImpersonatedRunImpersonatedAsync。 在此上下文中运行单个操作,然后关闭上下文。

app.Run(async (context) =>
{
    try
    {
        var user = (WindowsIdentity)context.User.Identity!;

        await context.Response
            .WriteAsync($"User: {user.Name}\tState: {user.ImpersonationLevel}\n");

        await WindowsIdentity.RunImpersonatedAsync(user.AccessToken, async () =>
        {
            var impersonatedUser = WindowsIdentity.GetCurrent();
            var message =
                $"User: {impersonatedUser.Name}\t" +
                $"State: {impersonatedUser.ImpersonationLevel}";

            var bytes = Encoding.UTF8.GetBytes(message);
            await context.Response.Body.WriteAsync(bytes, 0, bytes.Length);
        });
    }
    catch (Exception e)
    {
        await context.Response.WriteAsync(e.ToString());
    }
});

虽然 Microsoft.AspNetCore.Authentication.Negotiate 包可在 Windows、Linux 和 macOS 上启用身份验证,但仅 Windows 上支持模拟。

声明转换

使用 IIS 进行托管时,不会在内部调用 AuthenticateAsync 来初始化用户。 因此,默认情况下不激活每次身份验证后用于转换声明的 IClaimsTransformation 实现。 有关详细信息以及激活声明转换的代码示例,请参阅进程内托管和进程外托管之间的差异

其他资源

可以为由 IISKestrelHTTP.sys 托管的 ASP.NET Core 应用配置 Windows 身份验证(也称为 Negotiate、Kerberos 或 NTLM 身份验证)。

Windows 身份验证依赖于操作系统对 ASP.NET Core 应用进行身份验证。 当服务器在公司网络上运行,且公司网络使用 Active Directory 域标识或 Windows 帐户来标识用户时,可以使用 Windows 身份验证。 Windows 身份验证最适合用户、客户端应用和 Web 服务器属于同一 Windows 域的 Intranet 环境。

注意

Windows 身份验证不支持 HTTP/2。 身份验证质询可通过 HTTP/2 响应发送,但客户端必须在进行身份验证之前降级到 HTTP/1.1。

代理和负载均衡器方案

Windows 身份验证是一种有状态方案,主要用于 Intranet,其中的代理或负载均衡器通常不处理客户端和服务器之间流量的情况。 如果使用了代理或负载均衡器,则仅当代理或负载均衡器符合以下情况时 Windows 身份验证才起作用:

  • 处理身份验证。
  • 将用户身份验证信息传递给应用(例如,在请求头中),应用根据身份验证信息执行操作。

在使用代理和负载平衡器的环境中,Windows 身份验证的另一种选择是结合使用 Active Directory 联合服务 (ADFS) 和 OpenID Connect (OIDC)。

IIS/IIS Express

通过调用 Startup.ConfigureServices 中的 AddAuthenticationMicrosoft.AspNetCore.Server.IISIntegration 命名空间)来添加身份验证服务:

services.AddAuthentication(IISDefaults.AuthenticationScheme);

启动设置(调试程序)

启动设置的配置只会影响 IIS Express 的Properties/launchSettings.json文件,而不会为 Windows 身份验证配置 IIS。 IIS 部分介绍了服务器配置。

通过 Visual Studio 或 .NET Core CLI 提供的Web 应用程序模板可以配置为支持 Windows 身份验证,它会自动更新Properties/launchSettings.json文件。

新建项目

  1. 创建新项目。
  2. 选择“ASP.NET Core Web 应用程序”。 选择“下一步”。
  3. 在“项目名称”字段中提供名称。 确认“位置”条目正确无误或为项目提供位置。 选择“创建”。
  4. 选择“身份验证”下的“更改”。
  5. 在“更改身份验证”窗口中,选择“Windows 身份验证”。 选择“确定”。
  6. 选择“Web 应用程序”。
  7. 选择“创建”。

运行应用。 用户名显示在呈现的应用用户界面中。

现有项目

项目的属性会启用 Windows 身份验证并禁用匿名身份验证:

  1. 右键单击“解决方案资源管理器”中的项目,再选择“属性” 。
  2. 选择“调试”选项卡。
  3. 清除“启用匿名身份验证”复选框。
  4. 选择“启用 Windows 身份验证”复选框。
  5. 保存并关闭属性页。

或者,可以在launchSettings.json文件的iisSettings节点中配置属性:

"iisSettings": {
    "windowsAuthentication": true,
    "anonymousAuthentication": false,
    "iisExpress": {
        "applicationUrl": "http://localhost:52171/",
        "sslPort": 44308
    }
}

修改现有项目时,确认项目文件包括对 Microsoft.AspNetCore.App 元包Microsoft.AspNetCore.Authentication NuGet 包的包引用。

IIS

IIS 使用 ASP.NET Core 模块来托管 ASP.NET Core 应用。 通过 web.config 文件为 IIS 配置 Windows 身份验证。 以下部分介绍如何执行这些操作:

  • 提供一个本地 web.config 文件,该文件在部署应用时在服务器上激活 Windows 身份验证。
  • 使用 IIS 管理器配置已部署到服务器的 ASP.NET Core 应用的 web.config文件。

如果尚未这样做,请启用 IIS 来托管 ASP.NET Core 应用。 有关详细信息,请参阅 使用 IIS 在 Windows 上托管 ASP.NET Core

启用 IIS 角色服务进行 Windows 身份验证。 有关详细信息,请参阅在 IIS 角色服务中启用 Windows 身份验证(请参阅步骤 2)

IIS 集成中间件默认配置为自动对请求进行身份验证。 有关详细信息,请参阅使用 IIS 在 Windows 上托管 ASP.NET Core:IIS 选项 (AutomaticAuthentication)

默认情况下,ASP.NET Core 模块配置为将 Windows 身份验证令牌转发到应用。 有关详细信息,请参阅 ASP.NET Core 模块配置参考:aspNetCore 元素的属性

请使用下述任一方法:

  • 在发布和部署项目之前,请将以下 web.config 文件添加到项目根目录:

    <?xml version="1.0" encoding="utf-8"?>
    <configuration>
      <location path="." inheritInChildApplications="false">
        <system.webServer>
          <security>
            <authentication>
              <anonymousAuthentication enabled="false" />
              <windowsAuthentication enabled="true" />
            </authentication>
          </security>
        </system.webServer>
      </location>
    </configuration>
    

    如果项目是由 .NET Core SDK 发布的,(项目文件中的 <IsTransformWebConfigDisabled> 属性未设置为 true),则发布的 web.config 文件中包含 <location><system.webServer><security><authentication> 部分。 有关 <IsTransformWebConfigDisabled> 属性的详细信息,请参阅使用 IIS 在 Windows 上托管 ASP.NET Core

  • 发布和部署项目后,请使用 IIS 管理器执行服务器端配置:

    1. 在 IIS 管理器中,选择“连接”侧栏的“站点”节点下的 IIS 站点。
    2. 双击“IIS”区域中的“身份验证”。
    3. 选择“匿名身份验证”。 选择“操作”侧栏中的“禁用”。
    4. 选择 “Windows 身份验证” 。 选择“操作”侧栏中的“启用”。

    执行这些操作时,IIS 管理器会修改应用的 web.config 文件。 添加了一个 <system.webServer><security><authentication> 节点,其中包含 anonymousAuthenticationwindowsAuthentication 的更新设置:

    <system.webServer>
      <security>
        <authentication>
          <anonymousAuthentication enabled="false" />
          <windowsAuthentication enabled="true" />
        </authentication>
      </security>
    </system.webServer>
    

    IIS 管理器添加到 web.config 文件的 <system.webServer> 部分位于发布应用时 .NET Core SDK 添加的应用的 <location> 部分之外。 由于该部分是在 <location> 节点之外添加的,因此设置会被任何子应用继承到当前应用。 若要防止继承,请将添加的 <security> 部分移动到 .NET Core SDK 提供的 <location><system.webServer> 部分内。

    当使用 IIS 管理器添加 IIS 配置时,它只会影响该应用在服务器上的 web.config 文件。 如果服务器的 web.config 副本替换为项目的 web.config 文件,则应用的后续部署可能会覆盖服务器上的设置。 使用以下任一方法管理设置:

    • 在部署时覆盖文件后,使用 IIS 管理器重置 web.config 文件中的设置。
    • 使用设置在本地将 web.config 文件添加到应用。

Kestrel

Microsoft.AspNetCore.Authentication.Negotiate NuGet 包可与 Kestrel 结合使用,以支持在 Windows、Linux 和 macOS 上使用 Negotiate 和 Kerberos 进行 Windows 身份验证。

警告

凭据可以跨连接上的请求持久保存。 Negotiate 身份验证不能与代理一起使用,除非代理与 Kestrel 保持 1:1 的连接关联(持久连接)。

注意

Negotiate 处理程序检测基础服务器是否本机支持 Windows 身份验证,以及是否启用了该身份验证。 如果服务器支持 Windows 身份验证但其已被禁用,则会引发错误,要求启用服务器实现。 若在服务器中启用了 Windows 身份验证,Negotiate 处理程序会以透明方式将身份验证请求转发到该服务器。

通过调用 Startup.ConfigureServices 中的 AddAuthenticationAddNegotiate 来添加身份验证服务:

// using Microsoft.AspNetCore.Authentication.Negotiate;
// using Microsoft.Extensions.DependencyInjection;

services.AddAuthentication(NegotiateDefaults.AuthenticationScheme)
   .AddNegotiate();

通过调用 Startup.Configure 中的 UseAuthentication 来添加身份验证中间件:

app.UseAuthentication();

有关中间件的详细信息,请参阅 ASP.NET Core 中间件

Kerberos 身份验证和基于角色的访问控制 (RBAC)

Linux 或 macOS 上的 Kerberos 身份验证不为经过身份验证的用户提供任何角色信息。 若要向 Kerberos 用户添加角色和组信息,必须将身份验证处理程序配置为从 LDAP 域中检索角色。 最基本的配置仅指定要查询的 LDAP 域,并将使用经过身份验证的用户上下文来查询 LDAP 域:

services.AddAuthentication(NegotiateDefaults.AuthenticationScheme)
    .AddNegotiate(options =>
    {
        if (RuntimeInformation.IsOSPlatform(OSPlatform.Linux))
        {
            options.EnableLdap("contoso.com");
        }
    });

某些配置可能要求提供特定凭据才可查询 LDAP 域。 可以在以下突出显示的选项中指定凭据:

public void ConfigureServices(IServiceCollection services)
{
    services.AddDbContext<ApplicationDbContext>(options =>
        options.UseSqlServer(
            Configuration.GetConnectionString("DefaultConnection")));
    services.AddDatabaseDeveloperPageExceptionFilter();
    services.AddDefaultIdentity<IdentityUser>(options => options.SignIn.RequireConfirmedAccount = true)
        .AddEntityFrameworkStores<ApplicationDbContext>();

    services.AddAuthentication(NegotiateDefaults.AuthenticationScheme)
        .AddNegotiate(options =>
        {
            if (RuntimeInformation.IsOSPlatform(OSPlatform.Linux))
            {
                options.EnableLdap(settings =>
                {
                    settings.Domain = "contoso.com";
                    settings.MachineAccountName = "machineName";
                    settings.MachineAccountPassword = Configuration["Password"]
                });
            }
        });

    services.AddRazorPages();
}

默认情况下,Negotiate 身份验证处理程序会解析嵌套域。 在大型或复杂 LDAP 环境中,解析嵌套域可能会导致查找速度缓慢或每个用户使用大量内存。 可以使用 IgnoreNestedGroups 选项来禁用嵌套域解析。

允许匿名请求。 使用 ASP.NET Core 授权质询匿名身份验证请求。

AuthenticationScheme 需要 NuGet 包 Microsoft.AspNetCore.Authentication.Negotiate

Windows 环境配置

Microsoft.AspNetCore.Authentication.Negotiate 组件执行用户模式身份验证。 必须将服务主体名称 (SPN) 添加到运行服务的用户帐户,而不是计算机帐户。 在管理命令外壳中执行 setspn -S HTTP/myservername.mydomain.com myuser

Linux 和 macOS 环境配置

有关将 Linux 或 macOS 计算机加入到 Windows 域的说明,请参阅使用 Windows 身份验证 Kerberos 将 Azure Data Studio 连接到 SQL Server 一文。 可按照该说明为域中的 Linux 计算机创建计算机帐户。 必须将 SPN 添加到该计算机帐户。

注意

按照使用 Windows 身份验证 Kerberos 将 Azure Data Studio 连接到 SQL Server 一文中的指南操作时,可根据需要将 python-software-properties 替换为 python3-software-properties

将 Linux 或 macOS 计算机加入域后,还需要执行其他步骤才可使用 SPN 提供 keytab 文件

  • 在域控制器上,向计算机帐户添加新的 Web 服务 SPN:
    • setspn -S HTTP/mywebservice.mydomain.com mymachine
    • setspn -S HTTP/mywebservice@MYDOMAIN.COM mymachine
  • 使用 ktpass 生成 keytab 文件:
    • ktpass -princ HTTP/mywebservice.mydomain.com@MYDOMAIN.COM -pass myKeyTabFilePassword -mapuser MYDOMAIN\mymachine$ -pType KRB5_NT_PRINCIPAL -out c:\temp\mymachine.HTTP.keytab -crypto AES256-SHA1
    • 某些字段必须按照指示以大写字母指定。
  • 将 keytab 文件复制到 Linux 或 macOS 计算机。
  • 通过环境变量选择 keytab 文件:export KRB5_KTNAME=/tmp/mymachine.HTTP.keytab
  • 调用 klist 以显示当前可用的 SPN。

注意

keytab 文件包含域访问凭据并且必须受到相应保护。

HTTP.sys

HTTP.sys 支持使用 Negotiate、NTLM 或基本身份验证进行内核模式 Windows 身份验证。

通过调用 Startup.ConfigureServices 中的 AddAuthenticationMicrosoft.AspNetCore.Server.HttpSys 命名空间)来添加身份验证服务:

services.AddAuthentication(HttpSysDefaults.AuthenticationScheme);

将应用的 Web 主机配置为将 HTTP.sys 用于 Windows 身份验证(Program.cs)。 UseHttpSys 位于 Microsoft.AspNetCore.Server.HttpSys 命名空间中。

public class Program
{
    public static void Main(string[] args)
    {
        CreateHostBuilder(args).Build().Run();
    }

    public static IHostBuilder CreateHostBuilder(string[] args) =>
        Host.CreateDefaultBuilder(args)
            .ConfigureWebHostDefaults(webBuilder =>
            {
                webBuilder.UseStartup<Startup>()
                    .UseHttpSys(options =>
                    {
                        options.Authentication.Schemes = 
                            AuthenticationSchemes.NTLM | 
                            AuthenticationSchemes.Negotiate;
                        options.Authentication.AllowAnonymous = false;
                    });
            });
}

注意

HTTP.sys 通过 Kerberos 身份验证协议委托给内核模式身份验证。 Kerberos 和 HTTP.sys 不支持用户模式身份验证。 必须使用计算机帐户来解密从 Active Directory 获取的并由客户端转发到服务器的 Kerberos 令牌/票证,以便对用户进行身份验证。 注册主机的服务主体名称 (SPN),而不是应用的用户。

注意

Nano Server 版本 1709 或更高版本不支持 HTTP.sys。 若要将 Windows 身份验证和 HTTP.sys 用于 Nano Server,请使用 Server Core (microsoft/windowsservercore) 容器。 有关 Server Core 的详细信息,请参阅什么是 Windows Server 中的 Server Core 安装选项?

对用户授权

匿名访问的配置状态决定了在应用中使用 [Authorize][AllowAnonymous] 属性的方式。 以下两部分说明了如何处理不允许和允许的匿名访问配置状态。

不允许匿名访问

如果启用 Windows 身份验证并禁用匿名访问,则 [Authorize][AllowAnonymous] 属性无效。 如果将 IIS 站点配置为不允许匿名访问,则请求永远不会到达应用。 因此,[AllowAnonymous] 属性不适用。

允许匿名访问

如果启用了 Windows 身份验证和匿名访问,可使用 [Authorize][AllowAnonymous] 属性。 利用 [Authorize] 属性,可以保护需要进行身份验证的应用的终结点。 [AllowAnonymous] 属性替代允许匿名访问的应用中的 [Authorize] 属性。 有关属性用法的详细信息,请参阅 ASP.NET Core 中的简单授权

注意

默认情况下,无权访问页面的用户会看到一个空 HTTP 403 响应。 可以将 StatusCodePages 中间件配置为向用户提供更好的“拒绝访问”体验。

模拟

ASP.NET Core 不实现模拟。 应用使用应用池或进程标识,使用应用的标识运行所有请求。 如果应用应代表用户执行操作,请在Startup.Configure终端内联中间件中使用WindowsIdentity.RunImpersonatedRunImpersonatedAsync。 在此上下文中运行单个操作,然后关闭上下文。

app.Run(async (context) =>
{
    try
    {
        var user = (WindowsIdentity)context.User.Identity;

        await context.Response
            .WriteAsync($"User: {user.Name}\tState: {user.ImpersonationLevel}\n");

        WindowsIdentity.RunImpersonated(user.AccessToken, () =>
        {
            var impersonatedUser = WindowsIdentity.GetCurrent();
            var message =
                $"User: {impersonatedUser.Name}\t" +
                $"State: {impersonatedUser.ImpersonationLevel}";

            var bytes = Encoding.UTF8.GetBytes(message);
            context.Response.Body.Write(bytes, 0, bytes.Length);
        });
    }
    catch (Exception e)
    {
        await context.Response.WriteAsync(e.ToString());
    }
});

虽然 Microsoft.AspNetCore.Authentication.Negotiate 包可在 Windows、Linux 和 macOS 上启用身份验证,但仅 Windows 上支持模拟。

声明转换

使用 IIS 进行托管时,不会在内部调用 AuthenticateAsync 来初始化用户。 因此,默认情况下不激活每次身份验证后用于转换声明的 IClaimsTransformation 实现。 有关详细信息以及激活声明转换的代码示例,请参阅进程内托管和进程外托管之间的差异

其他资源