简体   繁体   English

WCF:偶尔拒绝客户端凭据

[英]WCF: Occasional rejection of client credentials

We are currently migrating services of an old WCF application to servers in a new domain.我们目前正在将旧 WCF 应用程序的服务迁移到新域中的服务器。 Since the migration the below mentioned error occurs from time to time.由于迁移,下面提到的错误不时发生。

An exception has occurred...发生了异常...

Exception Details: The server has rejected the client credentials.异常详细信息:服务器拒绝了客户端凭据。

System.ServiceModel.FaultException`1[System.ServiceModel.ExceptionDetail]: The server has rejected the client credentials. System.ServiceModel.FaultException`1[System.ServiceModel.ExceptionDetail]:服务器拒绝了客户端凭据。 (Fault Detail is equal to An ExceptionDetail, likely created by IncludeExceptionDetailInFaults=true, whose value is: (Fault Detail 等于 An ExceptionDetail,可能由 IncludeExceptionDetailInFaults=true 创建,其值为:

System.ServiceModel.Security.SecurityNegotiationException: The server has rejected the client credentials. System.ServiceModel.Security.SecurityNegotiationException:服务器拒绝了客户端凭据。

System.Security.Authentication.InvalidCredentialException: The server has rejected the client credentials. System.Security.Authentication.InvalidCredentialException:服务器拒绝了客户端凭据。

System.ComponentModel.Win32Exception: The logon attempt failed --- End of inner ExceptionDetail stack trace --- System.ComponentModel.Win32Exception: 登录尝试失败 --- 内部 ExceptionDetail 堆栈跟踪结束 ---

at System.Net.Security.NegoState.ProcessReceivedBlob(Byte[] message, LazyAsyncResult lazyResult)在 System.Net.Security.NegoState.ProcessReceivedBlob(Byte[] message, LazyAsyncResult lazyResult)
at System.Net.Security.NegoState.StartSendBlob(Byte[] message, LazyAsyncResult lazyResult)在 System.Net.Security.NegoState.StartSendBlob(Byte[] message, LazyAsyncResult lazyResult)
at System.Net.Security.NegoState.StartSendBlob(Byte[] message, LazyAsyncResult lazyResult)在 System.Net.Security.NegoState.StartSendBlob(Byte[] message, LazyAsyncResult lazyResult)
at System.Net.Security.NegoState.ProcessAuthentication(LazyAsyncResult lazyResult)在 System.Net.Security.NegoState.ProcessAuthentication(LazyAsyncResult lazyResult)
at System.Net.Security.NegotiateStream.AuthenticateAsClient(NetworkCredential credential, String targetName, ProtectionLevel requiredProtectionLevel, TokenImpersonationLevel allowedImpersonationLevel)在 System.Net.Security.NegotiateStream.AuthenticateAsClient(NetworkCredential credential, String targetName, ProtectionLevel requiredProtectionLevel, TokenImpersonationLevel allowedImpersonationLevel)
at...).在...)。

The difficult thing is that all calls work 95% of the time and there is no transparent reason a call suddenly fails.困难的是,所有呼叫都在 95% 的时间内有效,并且没有明确的原因导致呼叫突然失败。

The configurations and calls look like this:配置和调用如下所示:

Caller:呼叫者:

<binding name="Binding_ServiceTCP" 
         closeTimeout="00:30:00" openTimeout="00:30:00" 
         receiveTimeout="infinite" sendTimeout="infinite" 
         transferMode="Buffered" maxBufferSize="2147483647" 
         maxReceivedMessageSize="2147483647">
   <security mode="Transport">
       <transport clientCredentialType="Windows" />
   </security>
   <readerQuotas maxDepth="2147483647" maxArrayLength="2147483647" 
                 maxBytesPerRead="2147483647" maxNameTableCharCount="2147483647"  
                 maxStringContentLength="2147483647" />
</binding>

<Channel ChannelType="IWcfInterface" Name="ServiceName" 
         Binding="Binding_ServiceTCP" Address="net.tcp://serverinnewdomain:59886/Service" Identity="" />
objectOfIWcfInterfaceImplementingClass.WcfCall();

Recipient:接受者:

<service behaviorConfiguration="BehaviourName" name="ServiceName">
    <endpoint address="" binding="netTcpBinding" bindingConfiguration="Binding_ServiceTCP" contract="IWcfInterface" />
    <host>
        <baseAddresses>
            <add baseAddress="net.tcp://serverinnewdomain:59886/Service" />
        </baseAddresses>
    </host>
</service>
  
<behavior name="BehaviourName">
    <serviceMetadata httpGetEnabled="false" />
    <serviceDebug includeExceptionDetailInFaults="true" />
    <dataContractSerializer maxItemsInObjectGraph="2147483647" />
</behavior>
  
<binding name="Binding_ServiceTCP" 
         closeTimeout="00:30:00" openTimeout="00:30:00" 
         receiveTimeout="infinite" sendTimeout="infinite" 
         transferMode="Buffered" maxBufferSize="2147483647" 
         maxReceivedMessageSize="2147483647">
    <security mode="Transport">
        <transport clientCredentialType="Windows" />
    </security>
    <readerQuotas maxDepth="2147483647" maxArrayLength="2147483647" 
                  maxBytesPerRead="2147483647" maxNameTableCharCount="2147483647" 
                  maxStringContentLength="2147483647" />
</binding>
[ServiceContract(Namespace = "http://some.cool/namespace")]
[XmlSerializerFormat]
public interface IWcfInterface
{
    [OperationContract]
    [XmlSerializerFormat(SupportFaults = true)]
    SomeClass WcfCall();
}

The implementation is registered via castle.该实现是通过城堡注册的。

container.Register(Component.For<IWcfInterface>().ImplementedBy<WcfClass>().LifeStyle.PerWcfOperation());

on the old Servers .NET 4.7 is installed, 4.8 on the new ones.在旧服务器上安装 .NET 4.7,在新服务器上安装 4.8。

Suspecting that the credentials are somewhere lost on the way from Caller to Recipient I contacted the Network Team but they told me that this is not possible.我怀疑凭据在从呼叫者到接收者的途中丢失了,我联系了网络团队,但他们告诉我这是不可能的。

I would like to see which credentials arrive at the service.我想查看哪些凭据到达服务。 If this is not possible I also would be content with any other solution.如果这是不可能的,我也会满足于任何其他解决方案。

This is largely due to a Windows Domain mismatch and there are two solutions:这主要是由于 Windows 域不匹配造成的,有两种解决方案:

  1. Put both the application server and the client on the same Windows Domain.将应用程序服务器和客户端放在同一个 Windows 域中。

  2. If the machines are in the same domain, verify that the user account used to run the service is a domain account and not a local server account.如果计算机在同一个域中,请验证用于运行服务的用户帐户是域帐户而不是本地服务器帐户。

Note that if you use windows authentication, the client domain and server must be in the same windows domain.请注意,如果您使用 windows 身份验证,则客户端域和服务器必须在同一个 windows 域中。

Another solution is not to use windows authentication:另一种解决方案是不使用 Windows 身份验证:

<bindings>
  <netTcpBinding>
    <binding name="TcpBinding">
      <security mode="None"></security>
    </binding>
  </netTcpBinding>
</bindings>

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM