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





5.00/5 (2投票s)
一篇分步指南,帮助解决 .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 配置。根据我们的经验,有时在执行以下步骤后,需要很长时间才能使所有设置生效。
请按照以下步骤操作,您应该能够成功启用模拟。
- 在业务服务器上
- 打开命令提示符(以管理员身份运行)。
- 确保 TCP/IP 在“按顺序启用协议”列表中排在最前面。
- 确保“启用共享内存协议”未选中。
- 点击“确定”。
- 转到管理工具。
- 选择“用户权利指派”。
- 在右窗格中,双击“身份模拟经过身份验证的客户端”。
- 添加用户或组。
- 输入业务服务运行所在帐户的名称(这应该是与下面 SETSPN 命令中使用的帐户相同的帐户)。
- 单击“检查名称”。
- 名称解析为完整帐户名称后,选择该名称。
- 点击“确定”。
- 您将返回到“身份模拟经过身份验证的客户端”属性对话框。
- 点击“确定”。
- 在 SQL Server 上
- 展开“SQL Native Client 10.0 配置”节点(32 位)。
- 右键单击“客户端协议”并选择“属性”。
- 对“SQL Native Client 10.0 配置”节点执行相同操作。
- 转到“SQL Server 网络配置”。
- 在右窗格的列表中,确保“共享内存”和“TCP/IP”已启用。
- “命名管道”和“VIA”应禁用。
- 在业务服务运行所在域的 DC 上,或服务帐户用户所在的 DC 上
- SETSPN -A TestService/<business-service-host-name>.<fully-qualified-domain-name> <business-service-user-account-name>
- SETSPN -A MSSQLSvc/<sql-server-host-name>.<fully-qualified-domain-name>:1433 <sql-service-user-account-name>
- 在 AD 用户和计算机中
- 转到业务服务运行所在帐户的“属性”窗口。
- 选择“委派”选项卡。
- 选择“信任此用户以仅委派给指定服务”(这是受限委派)。
- 选择“仅使用 Kerberos”。
- 单击“添加...”按钮。
- 单击“用户或计算机...”按钮。
- 输入 SQL Server 运行所在帐户的名称(这应该是上面 SETSPN 命令中使用的帐户)。
- 单击“检查名称”。
- 名称解析为完整帐户名称后,选择该名称。
- 点击“确定”。
- 然后您将返回到“添加服务”对话框。
- 从“可用服务”列表中选择“MSSQLSvc”服务类型。
- 点击“确定”。
- 然后您将返回到帐户属性窗口。
- 单击“应用”。
- 点击“确定”。
- 转到 SQL Server 服务运行所在帐户的“属性”窗口。
- 选择“委派”选项卡。
- 选择“信任此用户以委派给任何服务(仅 Kerberos)”。
- 单击“应用”。
- 点击“确定”。
- 转到业务服务器计算机帐户的“属性”窗口。
- 选择“委派”选项卡。
- 确保已选择“信任此计算机以委派给任何服务(仅 Kerberos)”。
- 单击“应用”。
- 点击“确定”。
- 转到 SQL Server 计算机帐户的“属性”窗口。
- 选择“委派”选项卡。
- 确保已选择“信任此计算机以委派给任何服务(仅 Kerberos)”。
- 单击“应用”。
- 点击“确定”。
运行 cliconfg 命令。
选择“本地安全策略”。展开“本地策略”。
在“输入要选择的对象名称”框中
打开 SQL Server 配置管理器。
确保 TCP/IP 在“已启用协议”列表的顶部。
选择“MSSQLSERVER 的协议”。
打开命令提示符(以管理员身份运行)。运行以下命令
在“输入要选择的对象名称”框中
接下来我们做什么?
Sravan 和我获得了使用 WPF 与使用 nHibernate 与数据库通信的 WCF 业务层进行通信的大量经验。我们已经解决了 WPF 客户端在使用 WCF 时遇到的延迟加载、报告和常规最佳实践等问题。因此,我们将整理一篇关于如何使用这三种常用技术构建应用程序的文章。
历史
- 2009 年 8 月 14 日:初版。