簡體   English   中英

WCF - 在 HTTPS 情況下,未使用 HTTP.SYS 正確配置證書。 與 Charles 代理一起運行

[英]WCF - certificate not configured properly with HTTP.SYS in the HTTPS case. Works with Charles proxy running

這似乎是一個常見錯誤(還有其他具有類似問題的帖子) - 但是,我已經瀏覽了所有這些帖子和 MSDN 文章( https://docs.microsoft.com/en-us/dotnet/framework/wcf/功能詳細信息/使用證書)。 場景:嘗試訪問具有 HTTPS 端點的服務。 在代碼中設置客戶端證書(證書加載正確)。 至於服務器證書,我嘗試了以下兩個選項:client.ClientCredentials.ServiceCertificate.Authentication.CertificateValidationMode = X509CertificateValidationMode.None;

client.ClientCredentials.ServiceCertificate.Authentication.CertificateValidationMode = X509CertificateValidationMode.PeerOrChainTrust;

我已將服務器證書導入到個人和機器存儲(受信任的根證書頒發機構/證書)。 奇怪的是,當我使用 Charles Proxy 作為 SSL 代理時,調用正在進行。 其他設置:

    System.Net.ServicePointManager.SecurityProtocol = System.Net.SecurityProtocolType.Ssl3;

    ServicePointManager.ServerCertificateValidationCallback +=
            (se, cert, chain, sslerror) =>
            {
                //Console.WriteLine(cert.GetCertHashString());

                if (cert.GetCertHashString() == "[actual hash here]")
                    return true;
                else
                    return false;
            };

當 Charles 代理運行時,上述哈希檢查工作正常。 沒有代理運行,回調甚至不會被調用。

任何反饋表示贊賞。

(可能值得注意的是,使用 Apache CXF 庫的 Java 客戶端可以正常工作 - 針對相同的服務。)

更新:為了完整起見,原始錯誤也包含以下文本:這可能是由於在 HTTPS 情況下未使用 HTTP.SYS 正確配置服務器證書。 這也可能是由於客戶端和服務器之間的安全綁定不匹配造成的。

好的,經過幾天(和晚上)的頭部撞擊,以下是我的思考/發現(當然還有解決方案!):

  • 有“SSL”,然后是 SSLv2、SSLv3、TLSv1.0、TLSv1.1、TLS1.2 和 TLSv1.3(目前的草案)。

  • 服務器和客戶端能夠協商並選擇這些版本之一以成功通信至關重要。

  • HTTP.SYS 錯誤似乎是由於客戶端無法在適當的版本上與服務器協商的結果。 當通過 Charles 代理時,很明顯 Charles 和我們試圖訪問的服務都使用 TLSV1.1。

  • 就我而言,我使用的是 wsHTTPBinding & 雖然我嘗試設置 System.Net.ServicePointManager.SecurityProtocol = SecurityProtocolType.Tls; 和其他組合,我永遠無法讓 HTTP.SYS 錯誤消失。 服務器和客戶端似乎永遠無法選擇他們可以同意的版本。

  • 我確實嘗試使用其他綁定,例如 basicHttpBinding(使用 TransportWithMessageCredential)以及 basicHttpsBinding,但無濟於事。 更重要的是,在每種情況下對綁定元素(通過配置和代碼)進行了一些小調整,我在所有 3 種情況下都以完全相同的綁定配置結束(basicHttp/basichHttps/wsHttp 綁定)! 本質上,雖然有這些開箱即用的綁定,但它們可能適用於最簡單的場景。 更重要的是,可能不需要這么多這些預先打包的綁定,特別是因為它們似乎幾乎使用相同的綁定元素。

  • 我確實記得在許多情況下使用自定義綁定更好 - 但我想象通過自定義 wsHttpBinding 我將實現同樣的事情。 看起來不是 - 因為在這個綁定中有一些硬編碼的屬性(例如:默認 SSL 協議)似乎很難繞過。 我確實查看了 wsHttpBinding 及其基類的源代碼,但找不到確切的硬編碼位置(但在 System.ServiceModel 代碼中引用了“默認”協議)。

    • 最后一個“CustomBinding”對我有用,配置如下:

自定義綁定配置- 很抱歉將其作為圖像包含在內 - 因為 SO 上的格式正在播放。

  • 這個想法是使用httpsTransportrequireClientCertificate ,使用authenticationMode="CertificateOverTransport" & includeTimestamp="true" (我們的服務需要時間戳)和相關的messageSecurityVersion - 在我們的例子中是: WSSecurity10WSTrustFebruary2005WSSecureConversationFebruary2005WSSecurityPolicy11BasicSecurityProfile10 .

  • 上述配置也自動簽署了時間戳。

  • 最重要的是,我們必須包含用戶名/密碼憑據。 簡單地設置 client.ClientCredentials.UserName.UserName & client.ClientCredentials.UserName.Password 不會導致這些憑據包含在 Security 標頭中。 邏輯也是添加用戶名“令牌”,如下所示:

     //Get the current binding System.ServiceModel.Channels.Binding binding = client.Endpoint.Binding; //Get the binding elements BindingElementCollection elements = binding.CreateBindingElements(); //Locate the Security binding element SecurityBindingElement security = elements.Find<SecurityBindingElement>(); //This should not be null - as we are using Certificate authentication anyway if (security != null) { UserNameSecurityTokenParameters uTokenParams = new UserNameSecurityTokenParameters(); uTokenParams.InclusionMode = SecurityTokenInclusionMode.AlwaysToRecipient; security.EndpointSupportingTokenParameters.SignedEncrypted.Add(uTokenParams); } client.Endpoint.Binding = new CustomBinding(elements.ToArray());
  • 通過所有這些設置,我終於能夠點擊服務並實際得到結果 - 幾乎! - 因為結果不包括時間戳,WCF 將其作為異常拋出。 這是另一個需要解決的問題。

希望讀者發現這很有用。

更新:

  • 現在時間戳問題也“排序”了。 問題是響應缺少任何安全標頭,而不僅僅是時間戳。 幸運的是,有一種直接的方法可以通知 WCF 忽略不安全的響應,只需在安全元素上標記一個屬性:enableUnsecuredResponse="true"。 顯然這是不可取的,但由於我們對服務沒有任何控制權,這是我們目前能做的最好的事情。

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM