【问题标题】:WCF SslStreamSecurity DNS Identity Check failing for just 4.6 framework仅 4.6 框架的 WCF SslStreamSecurity DNS 身份检查失败
【发布时间】:2016-01-20 20:57:12
【问题描述】:

我正在为托管在 IIS 中的 Wcf 服务开发新的绑定,我以为我一切正常,但事实证明,如果我更改它,客户端仅在它以 .Net 框架 4.5 为目标时才有效以 4.6 为目标,然后在尝试打开连接时出现以下错误:

System.ServiceModel.Security.MessageSecurityException occurred
  HResult=-2146233087
  Message=The Identity check failed for the outgoing message. The remote endpoint did not provide a domain name system (DNS) claim and therefore did not satisfied DNS identity 'xxx.domain.local'. This may be caused by lack of DNS or CN name in the remote endpoint X.509 certificate's distinguished name.
  Source=System.ServiceModel
  StackTrace:
       at System.ServiceModel.Security.IdentityVerifier.EnsureIdentity(EndpointAddress serviceReference, AuthorizationContext authorizationContext, String errorString)

如果我只是将测试代码中的目标框架改回 4.5,那么它可以正常工作。这让我觉得这可能是 .Net 4.6 中的一个错误,我知道有 Wcf ssl changes made in 4.6

打开第一次机会异常后,我看到 System.ServiceModel 内部引发了以下异常

System.ArgumentNullException occurred
  HResult=-2147467261
  Message=Value cannot be null.
Parameter name: value
  ParamName=value
  Source=mscorlib
  StackTrace:
       at System.Enum.TryParseEnum(Type enumType, String value, Boolean ignoreCase, EnumResult& parseResult)
  InnerException: 

    System.ServiceModel.dll!System.ServiceModel.Security.IssuanceTokenProviderBase<System.ServiceModel.Security.Tokens.IssuedSecurityTokenProvider.FederatedTokenProviderState>.DoNegotiation(System.TimeSpan timeout)  Unknown     System.ServiceModel.dll!System.ServiceModel.Security.IssuanceTokenProviderBase<System.ServiceModel.Security.Tokens.IssuedSecurityTokenProvider.FederatedTokenProviderState>.GetTokenCore(System.TimeSpan timeout)   Unknown
    System.IdentityModel.dll!System.IdentityModel.Selectors.SecurityTokenProvider.GetToken(System.TimeSpan timeout) Unknown
    System.ServiceModel.dll!System.ServiceModel.Security.Tokens.IssuedSecurityTokenProvider.GetTokenCore(System.TimeSpan timeout)   Unknown
    System.IdentityModel.dll!System.IdentityModel.Selectors.SecurityTokenProvider.GetToken(System.TimeSpan timeout) Unknown
    System.ServiceModel.dll!System.ServiceModel.Security.SecurityProtocol.TryGetSupportingTokens(System.ServiceModel.Security.SecurityProtocolFactory factory, System.ServiceModel.EndpointAddress target, System.Uri via, System.ServiceModel.Channels.Message message, System.TimeSpan timeout, bool isBlockingCall, out System.Collections.Generic.IList<System.ServiceModel.Security.SupportingTokenSpecification> supportingTokens)    Unknown
    System.ServiceModel.dll!System.ServiceModel.Security.TransportSecurityProtocol.SecureOutgoingMessageAtInitiator(ref System.ServiceModel.Channels.Message message, string actor, System.TimeSpan timeout)    Unknown
    System.ServiceModel.dll!System.ServiceModel.Security.TransportSecurityProtocol.SecureOutgoingMessage(ref System.ServiceModel.Channels.Message message, System.TimeSpan timeout) Unknown
    System.ServiceModel.dll!System.ServiceModel.Security.SecurityProtocol.SecureOutgoingMessage(ref System.ServiceModel.Channels.Message message, System.TimeSpan timeout, System.ServiceModel.Security.SecurityProtocolCorrelationState correlationState)  Unknown
    System.ServiceModel.dll!System.ServiceModel.Channels.SecurityChannelFactory<System.ServiceModel.Channels.IRequestChannel>.SecurityRequestChannel.Request(System.ServiceModel.Channels.Message message, System.TimeSpan timeout) Unknown
    System.ServiceModel.dll!System.ServiceModel.Channels.TransactionRequestChannelGeneric<System.ServiceModel.Channels.IRequestChannel>.Request(System.ServiceModel.Channels.Message message, System.TimeSpan timeout)  Unknown
    System.ServiceModel.dll!System.ServiceModel.Dispatcher.RequestChannelBinder.Request(System.ServiceModel.Channels.Message message, System.TimeSpan timeout)  Unknown
    System.ServiceModel.dll!System.ServiceModel.Channels.ServiceChannel.Call(string action, bool oneway, System.ServiceModel.Dispatcher.ProxyOperationRuntime operation, object[] ins, object[] outs, System.TimeSpan timeout)  Unknown
    System.ServiceModel.dll!System.ServiceModel.Channels.ServiceChannelProxy.InvokeService(System.Runtime.Remoting.Messaging.IMethodCallMessage methodCall, System.ServiceModel.Dispatcher.ProxyOperationRuntime operation) Unknown
    System.ServiceModel.dll!System.ServiceModel.Channels.ServiceChannelProxy.Invoke(System.Runtime.Remoting.Messaging.IMessage message) Unknown
    mscorlib.dll!System.Runtime.Remoting.Proxies.RealProxy.PrivateInvoke(ref System.Runtime.Remoting.Proxies.MessageData msgData, int type) Unknown

正在与之通信的 wcf 服务的目标是 4.6,据我所知,我正在指定 dns 身份,它在证书主题中确实以 CN= 的形式存在。绑定是自定义绑定,因此我可以执行联合 net.tcp,客户端在代码中创建所有内容,并且我不使用 Visual Studio 中的添加服务引用功能,客户端代码正在创建绑定:

var binding = new CustomBinding(new BindingElement[] {
            new TransactionFlowBindingElement(),
            security,
            new SslStreamSecurityBindingElement(),
            new BinaryMessageEncodingBindingElement() {
                ReaderQuotas = { MaxDepth = maxReceivedSizeBytes, MaxStringContentLength = maxReceivedSizeBytes, MaxArrayLength = maxReceivedSizeBytes, MaxBytesPerRead = maxReceivedSizeBytes, MaxNameTableCharCount = maxReceivedSizeBytes },
            },
            new TcpTransportBindingElement {
                TransferMode = TransferMode.StreamedResponse,
                MaxReceivedMessageSize = maxReceivedSizeBytes,
            },
        }) {
    SendTimeout = sendTimeout,
};

var channelFactory = new ChannelFactory<T>(binding, new EndpointAddress(new Uri(url), EndpointIdentity.CreateDnsIdentity("xxx.domain.local"), new AddressHeader[0]));

这可能是 4.6 框架中的错误导致不同的行为吗?接下来的步骤是否只是尝试逐步调试框架代码以尝试找出 4.6 行为不同的原因?

编辑 - 我创建了一个small sample project that demonstrates the error,repro 步骤是:

  • (使用 VS 2015)打开 WcfSelfHostedServer 解决方案
  • 使用 mmc 将 IdentityFail.pfx 证书添加到本地计算机的个人存储中
  • 运行 WcfSelfHostedServer 项目(可能单击防火墙是允许端口 30000)
  • 打开 WcfClient 解决方案
  • 右键项目>属性,注意是针对4.6.1
  • 运行项目,会抛出上述异常
  • 现在将客户端切换到目标 4.5.2,它将正常运行,没有错误

更新 - 我发现以下似乎相关: https://support.microsoft.com/en-us/kb/3069494 https://msdn.microsoft.com/en-us/library/mt298998(v=vs.110).aspx

但是在服务器和客户端指定 Tls12 并不能解决问题,即使添加 DontEnableSchUseStrongCrypto=true 标志也不会影响 DNS 身份检查错误,即使它绕过了 was being thrown from this line 的 Enum.Parse 内部错误

【问题讨论】:

    标签: c# .net wcf .net-4.5 .net-4.6


    【解决方案1】:

    我需要查看Retargetting Changes in the .NET Framework 4.6.1,因为证书验证逻辑在该版本中发生了变化。 (change in behavior for X509CertificateClaimSet.FindClaims 导致了我的问题)

    修复正在编辑我的 app.config 以添加:

    <runtime>
        <AppContextSwitchOverrides value="Switch.System.IdentityModel.DisableMultipleDNSEntriesInSANCertificate=true" /> 
    </runtime>
    

    可以看到changed code on referencesource,自然makecert.exe好像不支持generating certificates with "Subject Alternative Name" fields

    【讨论】:

      【解决方案2】:

      您可以在代码中添加一行。

      像这样。

              AppContext.SetSwitch("Switch.System.IdentityModel.DisableMultipleDNSEntriesInSANCertificate",true);
      

      【讨论】:

      • 由于某种原因,这行得通,而 app.config 更改没有。
      • 我正在经历同样的事情。我在 web.config 的 runtime 部分设置了开关,但没有应用。不过,在代码中设置它是可行的(并且为我解决了这个问题)。我暂时没有解决方案......只是想我会插话。
      【解决方案3】:

      在服务器上安装 .net 4.7 为我解决了这个问题。

      【讨论】:

        【解决方案4】:

        布兰登。

        如果标志为“假”并且证书不包含 SAN 条目,我们似乎不会添加 dns 条目。

        【讨论】:

          猜你喜欢
          • 2011-03-31
          • 1970-01-01
          • 2021-11-20
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 2012-10-08
          • 1970-01-01
          相关资源
          最近更新 更多