2013-03-25 24 views
12

我有一个WCF由Windows服务托管的服务。如果我使用与服务运行时相同的凭据登录到客户端计算机,则客户端应用会成功,但如果我使用任何其他有效的域帐户登录,则会失败并出现异常。带SSPI的WCF Net.tcp失败,除非客户端和服务器使用相同的窗口身份

我有两个我正在测试的帐户,一个是普通用户帐户,另一个帐户是管理员帐户。我曾尝试下面列出的所有四种组合:

    Server account 
    CLient  RegUser AdminAcct 
    RegUser  Succeeds  Fails 
AdminAcct  Fails  Succeeds  

正如你所看到的系统当两个客户端和服务器的非管理员帐户下运行的工作不能是一个管理问题。 在这两种情况下,它没有我得到了同样的异常,在客户端,在服务器日志发生没有任何指示:“要SSPI调用失败,请参见内部异常”

内部例外是“目标原则名称不正确。”

我已经注册了账号为结节。

这个问题只发生在我的客户端应用程序中,但不是当我使用随Visual Studio提供的WCVFTestClient.exe

的例外,在WCF跟踪日志,是

“System.ServiceModel.Security.SecurityNegotiationException, System.ServiceModel,版本= 4.0.0.0,文化=中立, 公钥= b77a5c561934e089”

一条消息:

“验证失败在远程端(流可能仍然可以提供给更多认证尝试)“。

堆栈跟踪位于底部: 出了什么问题?

栈跟踪


System.ServiceModel.Channels.WindowsStreamSecurityUpgradeProvider.WindowsStreamSecurityUpgradeAcceptor.OnAcceptUpgrade(流 流,SecurityMessageProperty & remoteSecurity) System.ServiceModel.Channels.StreamSecurityUpgradeAcceptorBase.AcceptUpgrade(流 流) System.ServiceModel.Channels.InitialServerConnectionReader.UpgradeConnection(IConnection 连接,StreamUpgradeAcceptor upgradeAccept或者, IDefaultCommunicationTimeouts defaultTimeouts) System.ServiceModel.Channels.ServerSessionPreambleConnectionReader.ServerFramingDuplexSessionChannel.OnOpen(时间跨度 超时) System.ServiceModel.Channels.CommunicationObject.Open(时间跨度 超时) System.ServiceModel.Dispatcher.ChannelHandler。OpenAndEnsurePump() System.Runtime.ActionItem.DefaultActionItem.TraceAndInvoke() System.Runtime.ActionItem.CallbackHelper.InvokeWithoutContext(对象 状态) System.Runtime.IOThreadScheduler.ScheduledOverlapped.IOCallback(UInt32的 的errorCode,UInt32的的numBytes,NativeOverlapped * nativeOverlapped) System.Runtime.Fx.IOCompletionThunk.UnhandledExceptionFrame(UInt32的 误差,UInt32的bytesRead,nativeOverlapped * nativeOverlapped) System.Threading._IOCompletionCallback.PerformIOCompletionCallback(UInt32的 的errorCode,UInt32的的numBytes,nativeOverlapped * pOVERLAP)

回答

12

找到了答案。我的问题是两个因素的组合。

  1. 当使用net.tcp二进制WCF协议时,客户端安全模式确定是否使用NTLM或Kerberos进行身份验证。如果将客户端安全模式设置为“传输”,则身份验证将使用NTLM,并且只有一个跃点是可能的。如果您尝试让WCF服务器与第三个服务器(如数据库)交谈,它将会失败。使用SecurityMode =“消息”,otoh,导致WCF服务器使用Kerberos,它允许多跳...

  2. 第二个问题与我在绑定中在客户端上做了什么有关。 WCF协议net.tcp要求在客户端实例化端点时,必须指定一个“端点标识”(请参阅​​下面的代码)。我错误地认为这与认证有关,因此是客户端上当前登录的用户(Windows Principal)的身份。

    var epId = EndpointIdentity.CreateUpnIdentity(userPrincipalName); 
        var ep = new EndpointAddress(new Uri(url), epId): 
    

    否...在客户端上创建端点时必须指定的标识必须是服务器运行时的标识。这就是为什么当我使用与服务运行时相同的用户登录到客户端时代码工作的原因,并且当客户端是不同用户时失败。

    我仍然不明白为什么(服务帐户的)用户身份必须在客户端的端点中指定。这些数据需要什么功能在服务器上?

+0

非常感谢这个答案。经过数小时和数小时的尝试和错误,我尝试了这个解决方案,它的作用就像一个魅力!如果我们见面,我会给你一杯啤酒;-) – 2017-11-28 11:47:28

+0

非常欢迎!我去哪里拿到我的啤酒? 2017-11-28 14:26:41

+0

根据你的个人资料,我认为我们不会在不久的将来见面...但永不结束感谢会跟着你;-) – 2017-11-28 14:46:35

1

关于第二点,客户端不需要在服务器的相同Windows帐户下运行,以便成功进行身份验证,并且不需要在请求中手动指定帐户名称。据我所知,WCF认证是相互的,这意味着客户端也在验证服务器。

您收到的错误可能是由于客户端故障。如果将客户端的服务端点配置为提供ServicePrincipalName,则问题很可能得到解决。我发现this article对解决我遇到的同样问题很有帮助。

相关问题