简体   繁体   English

WCF - 在 HTTPS 情况下,未使用 HTTP.SYS 正确配置证书。 与 Charles 代理一起运行

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

This seems to be a common error (there are other posts with similar issues) - however, I have gone through all those posts and MSDN articles ( https://docs.microsoft.com/en-us/dotnet/framework/wcf/feature-details/working-with-certificates ).这似乎是一个常见错误(还有其他具有类似问题的帖子) - 但是,我已经浏览了所有这些帖子和 MSDN 文章( https://docs.microsoft.com/en-us/dotnet/framework/wcf/功能详细信息/使用证书)。 Scenario: Trying to access a service with an HTTPS end point.场景:尝试访问具有 HTTPS 端点的服务。 Setting the client certificate in code (certificate is loading correctly).在代码中设置客户端证书(证书加载正确)。 As for the Server cert, I have tried both the options below: client.ClientCredentials.ServiceCertificate.Authentication.CertificateValidationMode = X509CertificateValidationMode.None;至于服务器证书,我尝试了以下两个选项:client.ClientCredentials.ServiceCertificate.Authentication.CertificateValidationMode = X509CertificateValidationMode.None;

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

I have imported the server certificate to Personal as well as machine store (Trusted Root certificate authorities / certificates).我已将服务器证书导入到个人和机器存储(受信任的根证书颁发机构/证书)。 The weird thing is the call is going through when I use Charles Proxy as the SSL proxy.奇怪的是,当我使用 Charles Proxy 作为 SSL 代理时,调用正在进行。 Other settings:其他设置:

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

The above Hash check works fine when Charles proxy is running.当 Charles 代理运行时,上述哈希检查工作正常。 Without the proxy running, the callback does not even get called.没有代理运行,回调甚至不会被调用。

Any feedback is appreciated.任何反馈表示赞赏。

(It may be worthwhile to note that a Java client using Apache CXF library works fine - against the same service.) (可能值得注意的是,使用 Apache CXF 库的 Java 客户端可以正常工作 - 针对相同的服务。)

Update : For completeness, the original error also had this text: This could be due to the fact that the server certificate is not configured properly with HTTP.SYS in the HTTPS case.更新:为了完整起见,原始错误也包含以下文本:这可能是由于在 HTTPS 情况下未使用 HTTP.SYS 正确配置服务器证书。 This could also be caused by a mismatch of the security binding between the client and the server.这也可能是由于客户端和服务器之间的安全绑定不匹配造成的。

OK, after days(& nights) of head banging, the following are my musings / findings (& of course the solution !):好的,经过几天(和晚上)的头部撞击,以下是我的思考/发现(当然还有解决方案!):

  • There is "SSL" and then there is SSLv2, SSLv3, TLSv1.0, TLSv1.1, TLS1.2 & TLSv1.3 (draft as of now).有“SSL”,然后是 SSLv2、SSLv3、TLSv1.0、TLSv1.1、TLS1.2 和 TLSv1.3(目前的草案)。

  • It is critical that the server and client are able to negotiate & pick one of these versions to successfully communicate.服务器和客户端能够协商并选择这些版本之一以成功通信至关重要。

  • The HTTP.SYS error seems to be a result of the client not being able to negotiate with the server on the appropriate version. HTTP.SYS 错误似乎是由于客户端无法在适当的版本上与服务器协商的结果。 When going through Charles proxy, it was clear that both Charles and the service we were trying to hit, were using TLSV1.1.当通过 Charles 代理时,很明显 Charles 和我们试图访问的服务都使用 TLSV1.1。

  • In my case, I was using wsHTTPBinding & though I tried setting the System.Net.ServicePointManager.SecurityProtocol = SecurityProtocolType.Tls;就我而言,我使用的是 wsHTTPBinding & 虽然我尝试设置 System.Net.ServicePointManager.SecurityProtocol = SecurityProtocolType.Tls; and other combinations, I could never get the HTTP.SYS error to go away.和其他组合,我永远无法让 HTTP.SYS 错误消失。 It would seem that the server and the client could never pick a version that they could agree on.服务器和客户端似乎永远无法选择他们可以同意的版本。

  • I did try using other bindings such as basicHttpBinding (with TransportWithMessageCredential) as well as basicHttpsBinding, but to no avail.我确实尝试使用其他绑定,例如 basicHttpBinding(使用 TransportWithMessageCredential)以及 basicHttpsBinding,但无济于事。 What's more with some minor tweaks in the binding elements (through config & code) in each case, I ended with exactly the same binding configuration in all 3 cases (basicHttp/basichHttps/wsHttp bindings)!更重要的是,在每种情况下对绑定元素(通过配置和代码)进行了一些小调整,我在所有 3 种情况下都以完全相同的绑定配置结束(basicHttp/basichHttps/wsHttp 绑定)! In essence, while there are these out-of-the-box bindings, they probably work for the most simple of scenarios.本质上,虽然有这些开箱即用的绑定,但它们可能适用于最简单的场景。 What's more, there is probably no need for so many of these pre-packaged bindings, especially as they seem to be using mostly the same binding elements.更重要的是,可能不需要这么多这些预先打包的绑定,特别是因为它们似乎几乎使用相同的绑定元素。

  • I did remember reading that using a custom binding is better in many cases - but I imagined that by customizing a wsHttpBinding I would be achieving the same thing.我确实记得在许多情况下使用自定义绑定更好 - 但我想象通过自定义 wsHttpBinding 我将实现同样的事情。 Looks not - as there are some hard-coded properties (eg: default SSL protocols) in this binding that seem difficult to get around.看起来不是 - 因为在这个绑定中有一些硬编码的属性(例如:默认 SSL 协议)似乎很难绕过。 I did take a look at the source code of wsHttpBinding and its base class, but could not find the exact hard coded location (but there are references to "default" protocols in the System.ServiceModel code).我确实查看了 wsHttpBinding 及其基类的源代码,但找不到确切的硬编码位置(但在 System.ServiceModel 代码中引用了“默认”协议)。

    • In the end a "CustomBinding" worked for me, configured like so:最后一个“CustomBinding”对我有用,配置如下:

Custom Binding configuration - Sorry for including this as an image - as the formatting on SO was playing up.自定义绑定配置- 很抱歉将其作为图像包含在内 - 因为 SO 上的格式正在播放。

  • The idea is to use httpsTransport with requireClientCertificate , security with authenticationMode="CertificateOverTransport" & includeTimestamp="true" (our service required Timestamp) and the relevant messageSecurityVersion - in our case it was: WSSecurity10WSTrustFebruary2005WSSecureConversationFebruary2005WSSecurityPolicy11BasicSecurityProfile10 .这个想法是使用httpsTransportrequireClientCertificate ,使用authenticationMode="CertificateOverTransport" & includeTimestamp="true" (我们的服务需要时间戳)和相关的messageSecurityVersion - 在我们的例子中是: WSSecurity10WSTrustFebruary2005WSSecureConversationFebruary2005WSSecurityPolicy11BasicSecurityProfile10 .

  • The above configurations automatically signed the Timestamp as well.上述配置也自动签署了时间戳。

  • On top of this we had to include the username / password credentials.最重要的是,我们必须包含用户名/密码凭据。 Simply setting the client.ClientCredentials.UserName.UserName & client.ClientCredentials.UserName.Password did not result in these credentials included in the Security header.简单地设置 client.ClientCredentials.UserName.UserName & client.ClientCredentials.UserName.Password 不会导致这些凭据包含在 Security 标头中。 The logic was to add the username "token" as well, like so:逻辑也是添加用户名“令牌”,如下所示:

     //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());
  • With all this setup, I was able to finally hit the Service and actually get the result - well, almost !通过所有这些设置,我终于能够点击服务并实际得到结果 - 几乎! - as the result does not include a Timestamp, which WCF is throwing up as an exception. - 因为结果不包括时间戳,WCF 将其作为异常抛出。 That is another problem to solve though.这是另一个需要解决的问题。

Hopefully readers find this useful.希望读者发现这很有用。

Update:更新:

  • Now the Timestamp issue is also "sorted".现在时间戳问题也“排序”了。 The thing is the response lacked any security header, not just the timestamp.问题是响应缺少任何安全标头,而不仅仅是时间戳。 Thankfully there was a straightforward way to notify WCF to ignore unsecure responses, by simply marking an attribute on the security element: enableUnsecuredResponse="true".幸运的是,有一种直接的方法可以通知 WCF 忽略不安全的响应,只需在安全元素上标记一个属性:enableUnsecuredResponse="true"。 Obviously this is not desirable, but as we do not have any control on the service, this is the best we can do at the moment.显然这是不可取的,但由于我们对服务没有任何控制权,这是我们目前能做的最好的事情。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

相关问题 这可能是由于在 HTTPS 案例中未使用 HTTP.SYS 正确配置服务器证书。 c# - This could be due to the fact that the server certificate is not configured properly with HTTP.SYS in the HTTPS case. c# 在 HTTPS 情况下,服务器证书没有正确配置 HTTP.SYS - server certificate is not configured properly with HTTP.SYS in the HTTPS case WCF 错误“这可能是由于在 HTTPS 情况下未使用 HTTP.SYS 正确配置服务器证书” - WCF Error "This could be due to the fact that the server certificate is not configured properly with HTTP.SYS in the HTTPS case" 如何修复 Windows 7 上的“服务器证书未使用 HTTP.SYS 正确配置”? - How to fix “the server certificate is not configured properly with HTTP.SYS” on Windows 7? 使用HTTP.SYS未正确配置由证书服务器证书导致的SSL崩溃 - SSL crashes periodically caused by certificate server certificate is not configured properly with HTTP.SYS 没有HTTP.SYS的WCF - WCF without HTTP.SYS 使用http.sys的自托管WCF应用返回未找到路径的HTTP 503 - Self-hosted WCF app using http.sys returns HTTP 503 for path not found WCF通过HTTPS-&gt;代理-&gt; HTTP - WCF Through HTTPS -> Proxy -> HTTP 与JBoss / tomcat和HTTP.sys共享端口? - Sharing ports with JBoss/tomcat and HTTP.sys? WCF服务使用HTTP但不使用HTTPS - WCF Service works with HTTP but not with HTTPS
 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM