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 新手,虽然我什至不会声称自己是一个称职的用户,但我对绑定有了更多的了解。
通过使用 shotgun 调试,我实际上已经正确完成了几次,但我被我复制到代码中的用户名中的一个不可见的子字符(我相信^Z)欺骗了。
此外,我看到很多关于 BasicHttpBinding 不支持 https 的信息,情况更加复杂 - 如果你像这样创建它,它确实如此:
var binding = new BasicHttpBinding(BasicHttpSecurityMode.Transport);
感谢这篇相对较旧的文章教育我到弄清楚的地步:
https://msdn.microsoft.com/en-us/magazine/cc163394.aspx
从这篇文章中,我还了解到,如果 BasicHttpBinding 不支持 https,我本可以构建自己的 CustomBinding,用相对较少的努力来工作。
还要感谢我们的霸主乔恩·斯基特(Jon Skeet)将我推向正确的方向,弄清楚实际上通过电线发送的内容!