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

时间:2018-06-08 02:11:58

标签: wcf ssl soap https client-certificates

这似乎是一个常见的错误(还有其他帖子有类似的问题) - 但是,我已经浏览了所有这些帖子和MSDN文章(https://docs.microsoft.com/en-us/dotnet/framework/wcf/feature-details/working-with-certificates)。 场景:尝试使用HTTPS端点访问服务。 在代码中设置客户端证书(证书正确加载)。 至于服务器证书,我尝试了以下两个选项:   client.ClientCredentials.ServiceCertificate.Authentication.CertificateValidationMode = X509CertificateValidationMode.None;

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

我已将服务器证书导入Personal和机器商店(受信任的根证书颁发机构/证书)。 奇怪的是当我使用Charles Proxy作为SSL代理时,调用正在进行。 其他设置:

finishGame = () => {
  const scorePlayer = this.state.cardsPlayer.reduce((a, b) => a + b);

  const scoreDealer = this.state.cardsDealer.reduce((a, b) => a + b);

  for (let i = scoreDealer; scoreDealer < scorePlayer; i++) {

    this.setState({
      cardsDealer: this.state.cardsDealer.concat(this.state.cards.splice(0, 1))
    })

    if (scoreDealer === 21) {
      break;
    }
  }
}

当Charles代理运行时,上面的哈希检查工作正常。如果没有代理运行,回调甚至不会被调用。

感谢任何反馈。

(可能值得注意的是,使用Apache CXF库的Java客户端可以正常工作 - 针对相同的服务。)

更新: 为完整起见,原始错误也有此文本: 这可能是由于在HTTPS情况下未使用HTTP.SYS正确配置服务器证书。这也可能是由于客户端和服务器之间的安全绑定不匹配造成的。

1 个答案:

答案 0 :(得分:3)

好的,在头部撞击的几天(及以上)之后,以下是我的思考/发现(当然还有解决方案!):

  • 有&#34; SSL&#34;然后是SSLv2,SSLv3,TLSv1.0,TLSv1.1,TLS1.2&amp; TLSv1.3(截至目前的草案)。

  • 服务器和客户端能够协商并且至关重要。选择其中一个版本来成功沟通。

  • HTTP.SYS错误似乎是客户端无法在适当的版本上与服务器协商的结果。通过查尔斯代理时,很明显查尔斯和我们试图打击的服务都在使用TLSV1.1。

  • 就我而言,我使用的是wsHTTPBinding&amp;虽然我尝试设置System.Net.ServicePointManager.SecurityProtocol = SecurityProtocolType.Tls;和其他组合,我永远不会得到HTTP.SYS错误消失。似乎服务器和客户端永远不会选择他们可以同意的版本。

  • 我确实尝试过使用其他绑定,例如basicHttpBinding(使用TransportWithMessageCredential)以及basicHttpsBinding,但无济于事。在每种情况下,通过绑定元素(通过配置和代码)进行一些小调整,我结束了所有3种情况下完全相同的绑定配置(basicHttp / basichHttps / wsHttp绑定)!从本质上讲,虽然有这些开箱即用的绑定,但它们可能适用于最简单的场景。而且,可能不需要这么多预先打包的绑定,特别是因为它们似乎主要使用相同的绑定元素。

  • 我确实记得在很多情况下阅读使用自定义绑定更好 - 但我想通过自定义wsHttpBinding我会实现同样的目的。看起来没有 - 因为这个绑定中有一些硬编码属性(例如:默认SSL协议)似乎很难解决。我确实看了一下wsHttpBinding的源代码及其基类,但是找不到确切的硬编码位置(但是在System.ServiceModel代码中引用了#34;默认&#34;协议)。

    • 最后一个&#34; CustomBinding&#34;为我工作,配置如下:

Custom Binding configuartion - 抱歉将此作为图像包含 - 因为SO上的格式正在播放。

  • 我的想法是httpsTransportrequireClientCertificate一起使用,安全与authenticationMode="CertificateOverTransport" & includeTimestamp="true"(我们的服务需要时间戳)和相关messageSecurityVersion - 在我们的案例中是: WSSecurity10WSTrustFebruary2005WSSecureConversationFebruary2005WSSecurityPolicy11BasicSecurityProfile10

  • 以上配置也会自动为时间戳签名。

  • 除此之外,我们还必须包含用户名/密码凭据。只需设置client.ClientCredentials.UserName.UserName&amp; client.ClientCredentials.UserName.Password未导致Security头中包含这些凭据。逻辑是添加用户名&#34;令牌&#34;同样如此:

    //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将其作为例外引发。这是另一个需要解决的问题。

希望读者觉得这很有用。

<强>更新

  • 现在时间戳问题也是&#34;排序&#34;。问题是响应缺少任何安全标头,而不仅仅是时间戳。值得庆幸的是,通过简单地在安全元素上标记一个属性,有一种直接的方式来通知WCF忽略不安全的响应:enableUnsecuredResponse =&#34; true&#34;。显然这是不可取的,但由于我们对服务没有任何控制权,这是我们目前可以做的最好的事情。