【问题标题】:Can WCF access a SOAP 1.1 service using https?WCF 可以使用 https 访问 SOAP 1.1 服务吗?
【发布时间】:2015-03-07 13:42:07
【问题描述】:

我有一个 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 realm="bla bla service"'。

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

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

感谢您提供任何见解!

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

我突然想到了两件事:

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

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

不存在代理授权标头。

不存在授权标头。

然后第二个请求尝试使用如下所示的 Authorization 标头来解决此问题:

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

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

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

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

我对滥用 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 传递给为请求提供服务的实际机器。

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

【问题讨论】:

  • 你检查过client.ClientCredentials is 是否为非空吗?此外,请注意格式化您帖子中的代码 - 不需要缩进那么远。
  • 感谢您的评论,乔恩。是的,client.ClientCredentials 是一个真实的对象,忘记说了。设置用户名/密码。我会尝试修复缩进,粘贴时遇到这种情况。
  • 您检查过发送的内容吗? (使用 Wireshark 或类似的东西来查看发送的请求。)
  • 我尝试过 Wireshark 它,但如前所述,它使用的是 https,所以它是加密的,我无法轻松读取它。当然可能有一种我不知道的方法来解决这个问题......
  • 您或许可以使用 Fiddler2 拦截带有临时证书的 https。

标签: c# php wcf authentication soap


【解决方案1】:

所以我在这个问题上绕了一圈。我今天早上是作为 WCF 新手开始的,虽然我什至还不能声称自己是一个称职的用户,但我对绑定了解得更多。

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

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

var binding = new BasicHttpBinding(BasicHttpSecurityMode.Transport);

感谢这篇相对较旧的文章,它让我明白了这一点:

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

从这篇文章中我也了解到,如果 BasicHttpBinding 不支持 https,我可以构建自己的 CustomBinding 以相对较少的工作量工作。

还要感谢我们的霸主 Jon Skeet 将我推向正确的方向,以弄清楚实际上通过电线发送的内容!

【讨论】:

  • 帮了我很大的忙,谢谢!找到解决这个问题的方法真的很有趣。
猜你喜欢
  • 2023-03-24
  • 1970-01-01
  • 2015-06-15
  • 1970-01-01
  • 2012-01-28
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多