65.9K
CodeProject 正在变化。 阅读更多。
Home

如何在 .NET 和 Active Directory 中使用受限委派启用多跳模拟

starIconstarIconstarIconstarIconstarIcon

5.00/5 (2投票s)

2009 年 8 月 18 日

CPOL

5分钟阅读

viewsIcon

71303

一篇分步指南,帮助解决 .NET 多层开发人员面临的常见身份验证问题。

引言

考虑以下场景

  • 客户端计算机:XP。
  • 业务层服务器计算机:Windows Server 2008。
  • 数据库服务器计算机:Windows Server 2008/SQL Server 2008。
  • 客户端应用程序是一个使用 net.tcp 绑定的 WCF 客户端,用于访问业务层。
  • 业务层操作使用常规 SQL 客户端连接连接到 SQL Server。
  • 整个应用程序运行在 Active Directory 域内,并采用单一登录方法,因此最终用户无需登录应用程序。

如果您遇到常见的“多跳身份验证”问题,即客户端凭据无法通过中间层——换句话说,WCF 操作线程以 Windows 客户端用户的身份运行——但业务层尝试以“NT Authority\Anonymous User”身份向 SQL Server 进行身份验证,您可以使用以下设置来实现业务层的模拟。

客户端计算机运行的是 .NET 3.5 客户端应用程序。

客户端通过 WCF 与业务层通信,并且终结点已配置为委派。

请注意,此信息是从大量网站和论坛编译而来。数量太多,无法一一列出。我们从网上各个地方收集了零散的信息,但没有一个网站包含了所有内容。因此,我们整理了一篇文章,其中包含我们为使此功能正常工作所做的所有步骤。

<endpointBehaviors>
    <behavior name="defaultClientBehavior">
        <clientCredentials>
            <windows allowNtlm="false"
                     allowedImpersonationLevel="Delegation" />
            <httpDigest impersonationLevel="Delegation" />
        </clientCredentials>
    </behavior>
</endpointBehaviors>

<bindings>
    <netTcpBinding>
        <binding name="defaultBinding"
                 openTimeout="02:01:00"
                 receiveTimeout="02:10:00"
                 closeTimeout="02:02:00"
                 sendTimeout="02:02:00"
                 maxBufferSize="2147483647"
                 maxReceivedMessageSize="2147483647">
            <readerQuotas maxStringContentLength="5242880" />
            <security mode="Transport">
                <transport clientCredentialType="Windows"/>
            </security>
        </binding>
    </netTcpBinding>
</bindings>
<client>
    <endpoint address="net.tcp://businessServer.domain.local:51005/TestService"
              binding="netTcpBinding"
              bindingConfiguration="defaultBinding"
               behaviorConfiguration="defaultClientBehavior"
              contract="Business.Common.Services.ITestService"
              name="Business.Common.Services.ITestService">
        <identity>
            <servicePrincipalName value="TestService/ businessServer.domain.local " />
        </identity>
    </endpoint>
</client>

服务器计算机运行一组托管在 Windows 服务中的 WCF 服务。

WCF 服务使用 ORM 层通过常规 ADO.NET SQL Server 提供程序与 SQL Server 通信。

WCF 服务操作已配置为进行模拟。此处此方法的作用并不重要。您唯一需要关心的是 OperationBehavior 特性以及对 WindowsIdentity.Impersonate 的调用。

[OperationBehavior( Impersonation = ImpersonationOption.Required )]
public bool SaveTest( ref Core hc, ref IList testList )
{
  using ( ServiceSecurityContext.Current.WindowsIdentity.Impersonate( ) )
  {
    hc.Errors = new List<error>( );
    using ( ISession session = SessionFactory.GetSession( new ValidationInterceptor( hc ) ) )
    {
      using ( ITransaction transaction = session.BeginTransaction( ) )
      {
        foreach ( TestEntity alias in testList )
        {
          RepositoryFactory
                .Instance
                .Factory<testentity>( new ValidationInterceptor( hc ) 
                   as IInterceptor ).Save( session, transaction, hc, alias );
        }
        transaction.Commit( );
      }
    }
    return true;
  }
}

WCF 服务绑定已配置为 Windows 身份验证。

<behaviors>
    <serviceBehaviors>
        <behavior name="defaultBehavior">
            <serviceMetadata httpGetEnabled="false" />
            <serviceAuthorization impersonateCallerForAllOperations="true" />
            <serviceCredentials>
                <windowsAuthentication includeWindowsGroups="true" allowAnonymousLogons="false"/>
            </serviceCredentials>
        </behavior>
</behaviors>
<bindings>
    <netTcpBinding>
        <binding name="defaultBinding"
                 closeTimeout="02:02:00"
                 openTimeout="02:01:00"
                 receiveTimeout="02:10:00"
                 sendTimeout="02:02:00"
                 maxBufferSize="2147483647"
                 maxReceivedMessageSize="2147483647">
            <readerQuotas maxStringContentLength="5242880" />
            <reliableSession inactivityTimeout="02:10:00" />
            <security mode="Transport">
                <transport clientCredentialType="Windows"/>
            </security>
        </binding>
    </netTcpBinding>
</bindings>

<services>
    <service name="Business.Common.Services.TestService"
        behaviorConfiguration="defaultBehavior">
        <endpoint address="net.tcp://businessServer.domain.local:51005/TestService"
                  binding="netTcpBinding"
                  bindingConfiguration="defaultBinding"
                  name=" Business.Common.Services.ITestService"
                  contract="Business.Common.Services.ITestService"
                 >
            <identity>
                <servicePrincipalName value="TestService/businessServer.domain.local"/>
            </identity>
        </endpoint>
    </service>

现在是棘手的部分。Active Directory 配置。根据我们的经验,有时在执行以下步骤后,需要很长时间才能使所有设置生效。

请按照以下步骤操作,您应该能够成功启用模拟。

  1. 在业务服务器上
    1. 打开命令提示符(以管理员身份运行)。
    2. 运行 cliconfg 命令。

      1. 确保 TCP/IP 在“按顺序启用协议”列表中排在最前面。
      2. 确保“启用共享内存协议”未选中。
      3. 点击“确定”。
    3. 转到管理工具。
    4. 选择“本地安全策略”。展开“本地策略”。

    5. 选择“用户权利指派”。
      1. 在右窗格中,双击“身份模拟经过身份验证的客户端”。
        1. 添加用户或组。
        2. 在“输入要选择的对象名称”框中

          1. 输入业务服务运行所在帐户的名称(这应该是与下面 SETSPN 命令中使用的帐户相同的帐户)。
          2. 单击“检查名称”。
          3. 名称解析为完整帐户名称后,选择该名称。
          4. 点击“确定”。
      2. 您将返回到“身份模拟经过身份验证的客户端”属性对话框。
      3. 点击“确定”。
  2. 在 SQL Server 上
  3. 打开 SQL Server 配置管理器。

    1. 展开“SQL Native Client 10.0 配置”节点(32 位)。
    2. 右键单击“客户端协议”并选择“属性”。
    3. 确保 TCP/IP 在“已启用协议”列表的顶部。

    4. 对“SQL Native Client 10.0 配置”节点执行相同操作。
    5. 转到“SQL Server 网络配置”。
    6. 选择“MSSQLSERVER 的协议”。

      1. 在右窗格的列表中,确保“共享内存”和“TCP/IP”已启用。
      2. “命名管道”和“VIA”应禁用。
  4. 在业务服务运行所在域的 DC 上,或服务帐户用户所在的 DC 上
  5. 打开命令提示符(以管理员身份运行)。运行以下命令

    1. SETSPN -A TestService/<business-service-host-name>.<fully-qualified-domain-name> <business-service-user-account-name>
    2. SETSPN -A MSSQLSvc/<sql-server-host-name>.<fully-qualified-domain-name>:1433 <sql-service-user-account-name>
  6. 在 AD 用户和计算机中
    1. 转到业务服务运行所在帐户的“属性”窗口。
    2. 选择“委派”选项卡。
      1. 选择“信任此用户以仅委派给指定服务”(这是受限委派)。
        1. 选择“仅使用 Kerberos”。
        2. 单击“添加...”按钮。
        3. 单击“用户或计算机...”按钮。
        4. 在“输入要选择的对象名称”框中

          1. 输入 SQL Server 运行所在帐户的名称(这应该是上面 SETSPN 命令中使用的帐户)。
          2. 单击“检查名称”。
          3. 名称解析为完整帐户名称后,选择该名称。
          4. 点击“确定”。
          5. 然后您将返回到“添加服务”对话框。
            1. 从“可用服务”列表中选择“MSSQLSvc”服务类型。
            2. 点击“确定”。
      2. 然后您将返回到帐户属性窗口。
      3. 单击“应用”。
      4. 点击“确定”。
    3. 转到 SQL Server 服务运行所在帐户的“属性”窗口。
    4. 选择“委派”选项卡。
      1. 选择“信任此用户以委派给任何服务(仅 Kerberos)”。
      2. 单击“应用”。
      3. 点击“确定”。
    5. 转到业务服务器计算机帐户的“属性”窗口。
    6. 选择“委派”选项卡。
      1. 确保已选择“信任此计算机以委派给任何服务(仅 Kerberos)”。
      2. 单击“应用”。
      3. 点击“确定”。
    7. 转到 SQL Server 计算机帐户的“属性”窗口。
    8. 选择“委派”选项卡。
      1. 确保已选择“信任此计算机以委派给任何服务(仅 Kerberos)”。
      2. 单击“应用”。
      3. 点击“确定”。

接下来我们做什么?

Sravan 和我获得了使用 WPF 与使用 nHibernate 与数据库通信的 WCF 业务层进行通信的大量经验。我们已经解决了 WPF 客户端在使用 WCF 时遇到的延迟加载、报告和常规最佳实践等问题。因此,我们将整理一篇关于如何使用这三种常用技术构建应用程序的文章。

历史

  • 2009 年 8 月 14 日:初版。
© . All rights reserved.