WCF:偶尔拒绝客户端凭据

WCF: Occasional rejection of client credentials

我们目前正在将旧 WCF 应用程序的服务迁移到新域中的服务器。自迁移以来,不时出现以下错误。

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. (Fault Detail is equal to An ExceptionDetail, likely created by IncludeExceptionDetailInFaults=true, whose value is:

System.ServiceModel.Security.SecurityNegotiationException: The server has rejected the client credentials.

System.Security.Authentication.InvalidCredentialException: The server has rejected the client credentials.

System.ComponentModel.Win32Exception: The logon attempt failed --- End of inner ExceptionDetail stack trace ---

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

困难的是所有调用在 95% 的时间都有效,并且没有明确的调用突然失败的原因。

配置和调用如下所示:

来电者:

<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();

收件人:

<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();
}

实现是通过城堡注册的。

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

在旧服务器上安装 .NET 4.7,在新服务器上安装 4.8。

我怀疑凭据在从呼叫者到接收者的途中丢失了某个地方,我联系了网络团队,但他们告诉我这是不可能的。

我想看看哪些凭据到达了服务。如果这是不可能的,我也会对任何其他解决方案感到满意。

这主要是由于 Windows 域不匹配,有两种解决方案:

  1. 将应用服务器和客户端放在同一个 Windows 域中。

  2. 如果机器在同一个域中,请验证用于运行服务的用户帐户是域帐户而不是本地服务器帐户。

注意,如果使用windows认证,客户端域和服务器必须在同一个windows域中。

另一种解决方案是不使用 windows 身份验证:

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