除非客户端和服务器使用相同的Windows标识,否则带有sspi的WCF Net.tcp将失败

Cha*_*ana 13 security wcf sspi net.tcp

我有一个由Windows服务托管的WCF服务.如果我使用与运行服务相同的凭据登录到客户端计算机,则客户端应用程序会成功,但如果我使用任何其他有效域帐户登录,则会失败并出现异常.

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

                   Server account
   CLient      RegUser    AdminAcct   
  RegUser     Succeeds      Fails   
 AdminAcct     Fails       Succeeds    
Run Code Online (Sandbox Code Playgroud)

正如您所看到的那样,当客户端和服务器都在非管理员帐户下运行时,系统可以正常工作,因此不会出现管理问题.在它失败的两种情况下,我在客户端上得到相同的异常,并没有指示服务器日志中发生的任何事情:

"对SSPI的调用失败了.看内部异常"

内部异常是"目标原则名称不正确".

我已将帐户注册为SPN.

问题只发生在我的客户端应用程序中,但不是在我使用WCVFTestClient.exeVisual Studio附带的时候.

WCF跟踪日志中的例外是

"System.ServiceModel.Security.SecurityNegotiationException,System.ServiceModel,Version = 4.0.0.0,Culture = neutral,PublicKeyToken = b77a5c561934e089"

有消息:

"远程端的身份验证失败(流可能仍可用于其他身份验证尝试)."

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

堆栈跟踪


System.ServiceModel.Channels.WindowsStreamSecurityUpgradeProvider.WindowsStreamSecurityUpgradeAcceptor.OnAcceptUpgrade(流流,SecurityMessageProperty&remoteSecurity)System.ServiceModel.Channels.StreamSecurityUpgradeAcceptorBase.AcceptUpgrade(流流)System.ServiceModel.Channels.InitialServerConnectionReader.UpgradeConnection(IConnection连接,StreamUpgradeAcceptor upgradeAcceptor,IDefaultCommunicationTimeouts defaultTimeouts) System.ServiceModel.Channels.ServerSessionPreambleConnectionReader.ServerFramingDuplexSessionChannel.OnOpen(TimeSpan timeout)System.ServiceModel.Channels.CommunicationObject.Open(TimeSpan timeout)System.ServiceModel.Dispatcher.ChannelHandler.OpenAndEnsurePump()System.Runtime.ActionItem.DefaultActionItem.TraceAndInvoke() System.Runtime.ActionItem.CallbackHelper.InvokeWithoutContext(Object state)System.Runtime.IOThreadScheduler.ScheduledOverlapped.IOCallback(UInt32 errorCode,UInt32 numBytes,NativeOverlapped*nativeOverlapped)System.Run time.Fx.IOCompletionThunk.UnhandledExceptionFrame(UInt32错误,UInt32 bytesRead,NativeOverlapped*nativeOverlapped)System.Threading._IOCompletionCallback.PerformIOCompletionCallback(UInt32 errorCode,UInt32 numBytes,NativeOverlapped*pOVERLAP)

Cha*_*ana 14

找到了答案.我的问题是两个因素的结合.

  1. 使用net.tcp二进制WCF协议时,客户端安全模式确定是使用NTLM还是Kerberos进行身份验证.如果将客户端安全模式设置为"传输",则身份验证使用NTLM,并且只能进行一次跳转.如果您尝试让WCF服务器与第三台服务器(如数据库)通信,它将失败.使用SecurityMode ="Message",otoh,使WCF服务器使用Kerberos,允许多跳...

  2. 第二个问题与我在绑定客户端上所做的事情有关.WCF协议net.tcp要求在客户端上实例化端点时,必须指定"端点标识"(请参阅​​下面的代码).我错误地认为这与身份验证有某种关系,因此,它是客户端上当前登录用户(Windows Principal)的身份.

        var epId = EndpointIdentity.CreateUpnIdentity(userPrincipalName);
        var ep = new EndpointAddress(new Uri(url), epId):
    
    Run Code Online (Sandbox Code Playgroud)

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

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