WCF SslStreamSecurity DNS身份检查失败只是4.6框架 [英] WCF SslStreamSecurity DNS Identity Check failing for just 4.6 framework

查看:977
本文介绍了WCF SslStreamSecurity DNS身份检查失败只是4.6框架的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我正在开发在IIS托管WCF服务一个新的绑定工作,我想我得到的一切工作,但事实证明,客户只能当它被打靶Net框架4.5,如果我改变它目标4.6然后我得到以下错误,当我尝试打开一个连接:

I am working on developing a new binding for a Wcf service that is hosted in IIS, I thought I got everything working, but it turns out that the client only works when it is targetting .Net framework 4.5, if I change it to target 4.6 then I get the following error when I try to open a connection:

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 4.6

If I do nothing other than change the target framework in my test code back to 4.5, then it works fine. This makes me think that it could be a bug in .Net 4.6, I know there were Wcf ssl changes made in 4.6

做随着第一机会异常变化开启我看到了下面的异常,在内部引发System.ServiceModel

With first chance exceptions turned on I see the following exception that is raised internally in 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

传达给的目标是4.6 WCF服务,并尽量我可以告诉大家我指定的DNS认同,这确实存在一个CN的证书主题=。绑定是一个自定义绑定,这样我可以做联合的net.tcp,客户端创建代码一切,我并不在Visual Studio中,考虑创建绑定客户端代码中使用添加服务引用功能:

The wcf service being communicated to is targeting 4.6, and as far as I can tell I am specifying the dns identity, which does exist as a CN= in the cert subject. The binding is a custom binding so that I can do federated net.tcp, the client creates everything in code and I don't use the Add Service Reference feature in visual studio, the client code that is creating the binding:

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的表现有所不同。

Could this be a bug in the 4.6 framework causing different behavior? Would the next steps only be trying to step through and debug framework code to try and find why 4.6 is behaving differently?

修改 -
我创建了一个演示错误小样本项目中,再现步骤如下:

EDIT - I created a small sample project that demonstrates the error, the repro steps are:


  • (使用VS 2015)打开WcfSelfHostedServer解决方案

  • 的IdentityFail.pfx证书添加到本地计算机,个人存储使用MMC

  • 运行WcfSelfHostedServer项目(可能单击防火墙是允许端口30000)

  • 打开WcfClient解决方案

  • 右键单击项目>属性,请注意,这是目标定位4.6.1

  • 运行项目时,它会抛出上述

  • 现在切换客户端4.5.2目标,它将会运行得很好,没有任何错误
  • (Using VS 2015) Open the WcfSelfHostedServer solution
  • Add the IdentityFail.pfx cert to your Local Computer, Personal store using mmc
  • Run the WcfSelfHostedServer project (likely clicking firewall yes allow port 30000)
  • Open the WcfClient solution
  • Right click on project > properties, note that it is targetting 4.6.1
  • Run the project, it will throw the exception described above
  • Now switch the client to target 4.5.2, it will run fine with no errors

更新 -
口发现,出现相关的情况如下:
https://开头的支持。 microsoft.com/en-us/kb/3069494
https://msdn.microsoft.com/en-us/library/mt298998(v = vs.110)的.aspx

但在服务器和客户端指定Tls12没有解决问题,甚至添加DontEnableSchUseStrongCrypto = true标志没有影响,即使它周围的正在从该行抛出

But specifying Tls12 at the server and client didn't fix the issue, and even adding the DontEnableSchUseStrongCrypto=true flag didn't affect the DNS Identity Check error even though it got around the Enum.Parse internal error that was being thrown from this line

推荐答案

我需要看的 Retargetting变化在.NET Framework 4.6.1 ,如证书验证逻辑,在该版本中改变。在行为X509CertificateClaimSet.FindClaims 的(变化引起了我的问题)

I needed to look at Retargetting Changes in the .NET Framework 4.6.1, as certificate validation logic changed in that release. (change in behavior for X509CertificateClaimSet.FindClaims that was causing my issue)

的修复程序编辑我的app.config补充:

The fix is editing my app.config to add:

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

您可以看到的改变了referencesource 的代码,和自然makecert.exe未出现,以支持生成证书与主题备用名称字段

You can see the changed code on referencesource, and naturally makecert.exe doesn't appear to support generating certificates with "Subject Alternative Name" fields

这篇关于WCF SslStreamSecurity DNS身份检查失败只是4.6框架的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆