WCF 可以使用 https 访问 SOAP 1.1 服务吗?

Can WCF access a SOAP 1.1 service using https?

我有一个 SOAP 服务需要与 C# 应用程序进行通信。我有一个 PHP 测试应用程序,它今天使用相同的 SOAP 服务,使用标准的 SoapClient。

用法类似:

$options = array(
    'login' => $username,
    'password' => $password,
    'location' => "https://$serveruri/soap",
);

$service = new SOAPClient($wsdl, $options);

$retval = $service->SomeMethod($parameter);

这很好用。据我了解(我在 PHP 没用),因为我们没有设置身份验证选项,所以它应该与基本身份验证一起使用。

我正在尝试与 C# 中的同一个端点通信,但它一直提示我进行身份验证。我不确定如何重新创建相同的身份验证。我相信一些问题来自使用 https - 我过去曾使用 http 和 BasicHttpBinding 与类似的系统对话,但由于我必须通过 https 与这个系统对话,所以这不好。

所以我已经使用 SvcUtil 生成了一个客户端代理,我正在尝试与它交谈。这是我目前的绝望迭代:

var endpoint = new EndpointAddress(SoapUrl);

var binding = new WSHttpBinding(SecurityMode.Transport);
binding.Security.Transport.ClientCredentialType = HttpClientCredentialType.Basic;
binding.SendTimeout = new TimeSpan(0, 0, 10);

ServicePointManager.ServerCertificateValidationCallback +=
                (sender, cert, chain, sslPolicyErrors) => true;

var client = new soapServiceClient(binding, endpoint);

if (client.ClientCredentials != null)
{
   client.ClientCredentials.UserName.UserName = Settings.AuthenticationUsername;
   client.ClientCredentials.UserName.Password = Settings.AuthenticationPassword;
}

var retval = client.SomeMethod(parameter);

下面是 Jons 的评论:当我 运行 时,client.ClientCredentials 真的不是空的。 ReSharper 把它放在那里是为了阻止它自己唠叨。

当我 运行 执行此操作时,我从服务器收到 401 Unauthorized。我在 Visual Studio 2013 年得到以下信息:

附加信息:HTTP 请求未经客户端身份验证方案 'Basic' 授权。从服务器收到的身份验证 header 是 'Basic realm="bla bla service"'。

在这种情况下,如何让 WCF 表现得像 PHPs SOAPClient?

我应该使用其他绑定吗?我尝试了不同的 SecurityMode 值,我尝试了 Digest 身份验证,但它们无济于事。因为这是通过 https 发生的,所以我想我也不能使用 Wireshark ..

感谢任何见解!

编辑:乔恩建议试一试 Fiddler2。我打开了https解密并试了一下。

我突然想到两件事:

1) 当我在本地 运行 PHP 脚本(在我的机器上使用 EasyPHP 运行ning)时,它会联系 SOAP 服务器并获取数据。但是,Fiddler2 看不到此流量。

2) 当我 运行 我的应用程序在 Visual Studio 2013 年时,Fiddler2 确实 看到流量,并对其进行解密。我看到两次尝试联系 SOAP 端点;两者都得到 401 回复。第一个不包含授权信息(查看 Fiddler2 的 Inspectors -> Auth 部分),只是说:

不存在 Proxy-Authorization Header。

不存在授权 Header。

然后第二个请求尝试使用看起来有点像这样的授权 header 来解决这个问题:

存在授权Header:基本[一些哈希数据] 已解码Username:Password=[正确的用户名]:[正确的密码]

但如前所述 - 这仍然会从另一侧激起 401。

我不知道为什么 PHP 流量没有出现在 Fiddler2 中,但它非常清楚地从另一端接收实时数据。也许 PHP 没有以 Fiddler2 可以获取的方式使用网络堆栈,我不知道。

编辑 2:在 PHP 端进行了一堆肮脏的调试之后,我终于开始比较 [=86 的 request/response 周期=] 应用程序与 WCF 一个。这让我更接近了(不知何故我在 auth 用户名中得到了一个子字符,这导致了身份验证问题),但现在我正在与 ProtocolException 作斗争,这是由于我的绑定被设置为 Content-Type application/soap+xml,外部服务(我相信这是基于 Linux)返回 text/xml。

我对 Google 的理解是 text/xml 对于 SOAP 1.1 是常见的,而 application/soap+xml 是 SOAP 1.2 所使用的。

此外,我了解到 WCF BasicHttpBinding 支持 SOAP 1.1,而 WsHttpBinding 支持 SOAP 1.2。

由于此服务位于 public 互联网上,因此需要 https 以确保安全。我相信系统上的原始 SOAP 服务本身使用 HTTP,但它在需要 HTTPS 的网关后面,然后将其作为 HTTP 传递给为请求提供服务的实际框。

问题的核心就变成了:有没有办法让我通过 WCF 使用 HTTPS 访问 SOAP 1.1 服务?

所以我在这件事上兜了一圈。今天早上我作为一个 WCF 新手开始,虽然我什至还没有声称自己是一个有能力的用户,但我对绑定有了更多的了解。

通过使用 shotgun 调试,我实际上已经正确地完成了几次,但是我被我复制到我的代码中的用户名中的一个不可见的子字符(我相信是 ^Z)欺骗了。

另外,我看到很多关于 BasicHttpBinding 不支持 https 的信息,这使情况更加复杂 - 如果您这样创建它,它会支持:

var binding = new BasicHttpBinding(BasicHttpSecurityMode.Transport);

归功于这篇相对较旧的文章,它让我明白了这一点:

https://msdn.microsoft.com/en-us/magazine/cc163394.aspx

从这篇文章中,我还了解到,如果 BasicHttpBinding 不支持 https,我本可以构建自己的 CustomBinding,它的工作原理与此相同。

还要感谢我们的领主 Jon Skeet 将我推向正确的方向,让我弄清楚实际上通过网络发送了什么!