2016-01-20 26 views
11

我正在開發一個新的綁定爲Wcf服務託管在IIS中,我以爲我得到了一切工作,但事實證明,客戶端只有當它是打靶Net框架4.5,如果我改變它的目標4.6然後我得到以下錯誤,當我嘗試打開一個連接:WCF SslStreamSecurity DNS身份檢查失敗只是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,該再現步驟是:

  • (使用VS 2015年)打開WcfSelfHostedServer解決方案
  • 的IdentityFail.pfx證書添加到本地計算機,個人存儲使用mmc
  • 運行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標誌沒有影響,即使它周圍的Enum.Parse內部錯誤was being thrown from this line

回答

18

我需要得到DNS身份檢查錯誤請查看Retargetting Changes in the .NET Framework 4.6.1,因爲該版本中的證書驗證邏輯已更改。 (change in behavior for X509CertificateClaimSet.FindClaims這是造成我的問題)

此修復程序正在編輯我的應用程序。配置增加:

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

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

1

布蘭登。

看來如果標誌是'假'且證書不包含SAN條目,我們不會添加dns條目。

4

你可以在代碼中添加一行。

這樣子。

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

由於某種原因,這個工作和app.config更改沒有。 – Jazaret

+1

我正在經歷同樣的事情。我在web.config的'runtime'部分設置了開關,但它沒有得到應用。但是,在代碼中設置它(併爲我解決了這個問題)。我目前還沒有解決這個問題的方法......只是覺得我會插話。 – erlingormar

1

在服務器上安裝.net 4.7解決了我的問題。