Warning: file_get_contents(/data/phpspider/zhask/data//catemap/7/wcf/4.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
具有外部信任的WCF SSPI故障-选择性与域范围_Wcf_Active Directory_Cross Domain - Fatal编程技术网

具有外部信任的WCF SSPI故障-选择性与域范围

具有外部信任的WCF SSPI故障-选择性与域范围,wcf,active-directory,cross-domain,Wcf,Active Directory,Cross Domain,我在工作中遇到了一个问题,我们使用WCF进行SSO的应用程序在与其他域通信时,对域信任使用选择性身份验证时失败。这是在服务器2k8R2机器上,在其两个域的完整2k8R2功能级别(这是一个测试系统,因为我们有一个客户希望部署这种类型的东西) 基本上,我们有两个域,称它们为A和B。当我们在域之间建立完全的双向外部(而不是林)信任时,应用程序运行良好(当然,在将用户放入另一个域的适当组中之后)。然后,我们将关系从“域范围”认证转换为“选择性认证”。根据我们阅读的一些文档,我们需要将用户直接添加到AD中

我在工作中遇到了一个问题,我们使用WCF进行SSO的应用程序在与其他域通信时,对域信任使用选择性身份验证时失败。这是在服务器2k8R2机器上,在其两个域的完整2k8R2功能级别(这是一个测试系统,因为我们有一个客户希望部署这种类型的东西)

基本上,我们有两个域,称它们为A和B。当我们在域之间建立完全的双向外部(而不是林)信任时,应用程序运行良好(当然,在将用户放入另一个域的适当组中之后)。然后,我们将关系从“域范围”认证转换为“选择性认证”。根据我们阅读的一些文档,我们需要将用户直接添加到AD中每台计算机的条目中,并授予他们“允许认证”权限

它不起作用

此外,我们在其他地方看到,这意味着我们还必须给他们在DC上的相同权限。就这样做了。再一次,失败

应用程序引发的异常如下(我将其转储到一个文件中)

基本上就是这样。正在发生某种类型的“授权异常”。正如我所说的,当它是一个域范围的双向信任时,它不会发生,所以我们认为我们缺少一些设置来“重新启用”使其工作。是否有人非常了解信任,能够为我们指明正确的方向,以支持选择性身份验证并使SSO/SSPI为此工作?它已经在整个领域内发挥了作用,但是我们需要开放什么才能让它为选择性的(而且更倾向于只为我们希望它为之工作的用户)发挥作用呢


谢谢。

打电话给Microsoft后,问题解决了:我们没有对主机上运行服务的许多用户授予“允许验证”权限。这些文档都提到必须在您正在访问的计算机(在某些情况下包括DC)上向您的客户端授予该权限,但没有提到必须将远程客户端添加到运行服务的主机用户的“安全”选项卡

因此,我将总结一些人为的用户、域和机器名,以及一个默认存在的实际服务帐户

“A”域:客户端试图从中连接的域 “B”域:这是域a中的用户正在连接的服务所在的计算机所在的域。 Client@A:来自A域的用户连接到B域中的服务。 ServiceAccount@B:承载WCF服务的B域中的用户Client@A正在连接到。 krbtgt@B:这是一个内置用户,其描述为“关键配送中心服务帐户”。只要您在“查看”菜单下启用了“高级功能”,它将位于Active Directory用户和计算机的“用户”下。除非你那样做,否则它根本不会出现。 B-DC:域B的域控制器 B-host:我们连接到的WCF服务的主机

所以,让Client@A连接到用户在B主机上运行的WCF服务ServiceAccount@B通过使用SSPI/Windows身份验证,在具有选择性身份验证的外部信任上,您需要执行以下操作:

  • 打开广告用户和计算机,在“查看”菜单下启用“高级功能”
  • 找到B-DC对象(默认情况下位于域控制器下,但如果已移动它,则可能位于其他位置)并打开“安全”选项卡。除非在步骤1中启用了高级功能,否则该选项卡将不存在。添加Client@A用户访问组或用户名,并确保为该用户选中了“读取”和“允许验证”
  • 找到B-host对象(默认情况下位于Computers下,但如果移动了它,则可能位于其他位置),并打开“security”选项卡。除非在步骤1中启用了高级功能,否则该选项卡将不存在。添加Client@A用户访问组或用户名,并确保为该用户选中了“读取”和“允许验证”
  • 找到krbtgt@B“用户”下的用户。如果未启用“高级功能”,帐户本身将不可见。转到“安全性”选项卡并添加Client@A选中“允许进行身份验证”和“读取”权限的用户
  • 找到serviceaccount@B用户,并执行与krbtgt相同的操作
  • 现在应该可以了。奇怪的是,你只需要在边界上运行一个windows身份验证(所以不是证书)WCF连接就可以了,但你就可以做到了。您需要将远程用户添加到AD中的四个不同对象才能使其正常工作。可能将远程用户添加到域B中具有正确权限的某些域本地组也会起作用,但这尚未测试

    编辑:然后在不到一小时的时间内,让PDC仿真器以AdminsHolder上的权限覆盖krbtgt。每小时

    基本上,krbtgt是超级保护的。你必须改变你的想法,这会带来很多麻烦。仅添加“允许进行身份验证”的命令为:

    如果您想了解“dsacls”工具的更多功能,请查阅该工具。它对于修改访问控制列表和打印它们都非常方便。事实上,它比GUI要好

    不管怎么说,这实际上现在起作用了。这是完整的答案

    A call to SSPI failed, see inner exception. Stacktrace: 
    Server stack trace: 
       at System.ServiceModel.Channels.WindowsStreamSecurityUpgradeProvider.WindowsStreamSecurityUpgradeInitiator.OnInitiateUpgrade(Stream stream, SecurityMessageProperty& remoteSecurity)
       at System.ServiceModel.Channels.StreamSecurityUpgradeInitiatorBase.InitiateUpgrade(Stream stream)
       at System.ServiceModel.Channels.ConnectionUpgradeHelper.InitiateUpgrade(StreamUpgradeInitiator upgradeInitiator, IConnection& connection, ClientFramingDecoder decoder, IDefaultCommunicationTimeouts defaultTimeouts, TimeoutHelper& timeoutHelper)
       at System.ServiceModel.Channels.ClientFramingDuplexSessionChannel.SendPreamble(IConnection connection, ArraySegment`1 preamble, TimeoutHelper& timeoutHelper)
       at System.ServiceModel.Channels.ClientFramingDuplexSessionChannel.DuplexConnectionPoolHelper.AcceptPooledConnection(IConnection connection, TimeoutHelper& timeoutHelper)
       at System.ServiceModel.Channels.ConnectionPoolHelper.EstablishConnection(TimeSpan timeout)
       at System.ServiceModel.Channels.ClientFramingDuplexSessionChannel.OnOpen(TimeSpan timeout)
       at System.ServiceModel.Channels.CommunicationObject.Open(TimeSpan timeout)
       at System.ServiceModel.Channels.ServiceChannel.OnOpen(TimeSpan timeout)
       at System.ServiceModel.Channels.CommunicationObject.Open(TimeSpan timeout)
       at System.ServiceModel.Channels.ServiceChannel.CallOnceManager.CallOnce(TimeSpan timeout, CallOnceManager cascade)
       at System.ServiceModel.Channels.ServiceChannel.EnsureOpened(TimeSpan timeout)
       at System.ServiceModel.Channels.ServiceChannel.Call(String action, Boolean oneway, ProxyOperationRuntime operation, Object[] ins, Object[] outs, TimeSpan timeout)
       at System.ServiceModel.Channels.ServiceChannelProxy.InvokeService(IMethodCallMessage methodCall, ProxyOperationRuntime operation)
       at System.ServiceModel.Channels.ServiceChannelProxy.Invoke(IMessage message)
    
    Exception rethrown at [0]: 
       at System.Runtime.Remoting.Proxies.RealProxy.HandleReturnMessage(IMessage reqMsg, IMessage retMsg)
       at System.Runtime.Remoting.Proxies.RealProxy.PrivateInvoke(MessageData& msgData, Int32 type)
    (A couple of calls in our own code below here)
    InnerException: System.Security.Authentication.AuthenticationException: A call to SSPI failed, see inner exception. ---> System.ComponentModel.Win32Exception: Unknown error (0xc0000413)
       --- End of inner exception stack trace ---
       at System.Net.Security.NegoState.ProcessAuthentication(LazyAsyncResult lazyResult)
       at System.Net.Security.NegotiateStream.AuthenticateAsClient(NetworkCredential credential, String targetName, ProtectionLevel requiredProtectionLevel, TokenImpersonationLevel allowedImpersonationLevel)
       at System.ServiceModel.Channels.WindowsStreamSecurityUpgradeProvider.WindowsStreamSecurityUpgradeInitiator.OnInitiateUpgrade(Stream stream, SecurityMessageProperty& remoteSecurity) 
    
    dsacls "[DN of object]" /g "[groupname]:ca;allowed to authenticate"