WCF 是否可以使用 https 访问 SOAP 1.1 服务

本文关键字:SOAP 服务 访问 https 是否 可以使 WCF | 更新日期: 2024-10-31 15:36:16

我有一个 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);

并解决琼斯下面的评论:客户。当我运行它时,客户端凭据确实不为空。ReSharper把它放在那里是为了阻止自己唠叨。

当我运行它时,我从服务器收到 401 未授权。我在Visual Studio 2013中得到以下信息:

其他信息:HTTP 请求未经授权,客户端身份验证方案"基本"。从服务器收到的身份验证标头是"Basic realm="bla bla service"。

在这种情况下,如何让 WCF 的行为像 PHP SOAPClient 一样?

我应该使用其他绑定吗?我尝试了不同的安全模式值,我尝试了摘要式身份验证,但它们无处可去。由于这发生在https上,我想我也不能Wireshark它。

感谢您的任何见解!

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

有两件事突然出现在我面前:

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

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

不存在代理授权标头。

不存在授权标头。

然后第二个请求尝试使用看起来像这样的授权标头来修复它:

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

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

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

编辑2:在PHP端进行了一堆肮脏的调试之后,我终于可以将PHP应用程序的请求/响应周期与WCF应用程序进行比较。这让我更接近(不知何故,我在身份验证用户名中加入了一个子字符,这导致了身份验证问题),但现在我正在努力解决 ProtocolException,这是我的绑定设置为内容类型应用程序/soap+xml 和外部服务(我相信这是基于 Linux 的)返回文本/xml。

我从滥用Google的理解是,text/xml在SOAP 1.1中很常见,而application/soap+xml是SOAP 1.2中使用的。

另外,我知道在WCF BasicHttpBinding中支持SOAP 1.1,而WsHttpBinding支持SOAP 1.2。

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

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

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)将我推向正确的方向,弄清楚实际上通过电线发送的内容!