gpt4 book ai didi

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

转载 作者:太空宇宙 更新时间:2023-11-03 12:57:51 34 4
gpt4 key购买 nike

这似乎是一个常见错误(还有其他类似问题的帖子) - 但是,我已经阅读了所有这些帖子和 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;

我已将服务器证书导入个人以及机器存储(受信任的根证书颁发机构/证书)。
奇怪的是,当我使用 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 正确配置服务器证书。这也可能是由于客户端和服务器之间的安全绑定(bind)不匹配造成的。

最佳答案

好的,经过几天(和几天)的头部撞击,以下是我的思考/发现(当然还有解决方案!):

  • 有“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 错误消失。似乎服务器和客户端永远无法选择他们可以同意的版本。
  • 我确实尝试使用其他绑定(bind),例如 basicHttpBinding(带有 TransportWithMessageCredential)以及 basicHttpsBinding,但无济于事。更重要的是,在每种情况下对绑定(bind)元素(通过配置和代码)进行了一些小的调整,我在所有 3 种情况下(basicHttp/basichHttps/wsHttp 绑定(bind))都以完全相同的绑定(bind)配置结束!本质上,虽然有这些开箱即用的绑定(bind),但它们可能适用于最简单的场景。更重要的是,可能不需要这么多这些预先打包的绑定(bind),尤其是因为它们似乎使用了几乎相同的绑定(bind)元素。
  • 我确实记得读过在许多情况下使用自定义绑定(bind)更好 - 但我想象通过自定义 wsHttpBinding 我会实现同样的目标。看起来不是——因为这个绑定(bind)中有一些硬编码的属性(例如:默认 SSL 协议(protocol))似乎很难绕过。我确实查看了 wsHttpBinding 及其基类的源代码,但找不到确切的硬编码位置(但在 System.ServiceModel 代码中有对“默认”协议(protocol)的引用)。
  • 最后,“CustomBinding”为我工作,配置如下:

  • Custom Binding configuration
    - 很抱歉将此作为图像包含在内 - 因为 SO 上的格式正在播放。
  • 这个想法是使用 httpsTransportrequireClientCertificate , 安全与 authenticationMode="CertificateOverTransport" & includeTimestamp="true" (我们的服务需要时间戳)和相关的messageSecurityVersion - 在我们的例子中是:WSSecurity10WSTrustFebruary2005WSSecureConversationFebruary2005WSSecurityPolicy11BasicSecurityProfile10 .
  • 上述配置也自动签署了时间戳。
  • 最重要的是,我们必须包括用户名/密码凭据。简单地设置 client.ClientCredentials.UserName.UserName & client.ClientCredentials.UserName.Password 不会导致这些凭据包含在 Security header 中。逻辑是添加用户名“token”,如下所示:
    //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 将其作为异常抛出。这是另一个需要解决的问题。

  • 希望读者觉得这很有用。

    更新:
  • 现在时间戳问题也被“排序”了。问题是响应缺少任何安全 header ,而不仅仅是时间戳。值得庆幸的是,有一种直接的方法可以通知 WCF 忽略不安全的响应,只需在安全元素上标记一个属性:enableUnsecuredResponse="true"。显然这是不可取的,但由于我们对服务没有任何控制权,这是我们目前能做的最好的。
  • 关于WCF - 在 HTTPS 情况下未使用 HTTP.SYS 正确配置证书。与 Charles 代理一起运行,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/50752410/

    34 4 0
    Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
    广告合作:1813099741@qq.com 6ren.com