【问题标题】:Invoking WCF service with PHP (with federated security)使用 PHP 调用 WCF 服务(具有联合安全性)
【发布时间】:2015-10-01 16:52:06
【问题描述】:

我正在尝试从 PHP 调用 WCF 服务 (.NET)。这比仅使用 SoapClient 稍微复杂一些,因为服务使用 WS2007FederationHttpBinding 进行身份验证。

这是我目前正在使用的代码。我什至没有添加凭据,因为我不确定如何添加,但无论如何,我什至还没有遇到拒绝访问错误。

$wsdl = "https://slc.centershift.com/sandbox40/StoreService.svc?wsdl";
$client = new SoapClient($wsdl,array(
         //'soap_version'=>SOAP_1_2 // default 1.1, but this gives 'Uncaught SoapFault exception: [HTTP] Error Fetching http headers'
        ));
$params = array();
$params['SiteID'] = 123;
$params['GetPromoData'] = false;

$ret = $client->GetSiteUnitData(array('GetSiteUnitData_Request'=>$params));
print_r($ret);
  1. 我应该指向哪个 WSDL?

    • @987654321@<strong>?wsdl</strong>
      似乎很短,但包含对(注意wsdl0@987654322@<strong>?wsdl=wsdl0</strong> 的引用
    • @987654323@<strong>?singleWsdl</strong>
      似乎什么都有。
  2. 是否需要指定 SOAP 1.2?当我这样做时,我得到一个连接超时 ([HTTP] Error Fetching http headers)。如果我不这样做,则使用 SOAP 1.1 的默认值,我得到一个 [HTTP] Cannot process the message because the content type 'text/xml; charset=utf-8' was not the expected type 'application/soap+xml; charset=utf-8'。这是因为我还没有通过身份验证,还是因为我使用了错误的 SOAP 版本?

  3. 如何在 PHP 中进行身份验证?这是相应的 .NET/C# 代码。我是否需要以某种方式将这些作为 SOAP 标头?还是我认为这一切都错了,我什至需要在调用该方法之前进行某种身份验证(根据我所读到的,我应该取回一个令牌,然后将其用于所有未来的方法调用——我我想我在an answer here on Stack Overflow 中看到了一个例子。

如果我使用 WSDL 和 SOAP 版本调用 $client-&gt;__getFunctions(),我将获得所有函数的有效列表,因此我假设其中任何一个都可以,而我真正的问题是身份验证。

与我交谈过的其他程序员曾花时间试图让它工作,但放弃了,而是在 .NET 中实现了一个代理。他们将参数从 PHP 传递到他们自己的不安全的 .NET 服务,该服务又调用此安全服务。它可以工作,但对我来说似乎效率极低,而且适得其反,因为 WCF 的目的是支持所有类型的客户端(甚至是非 HTTP 客户端!)。

我在 MSDN 上读过 How to: Create a WSFederationHttpBinding,但没有帮助。

【问题讨论】:

  • ?wsdl 或 ?singleWsdl 都可以。前者引用了按目的拆分的多个文档,后者将所有文档集中在一个地方。 wsdl 确实指定了正在使用的soap 版本,所以在它下载了wsdl 之后仍然需要告诉它使用哪个soap 版本似乎很奇怪。如果除了 wsdl 之外还需要提供此基本信息,我会建议该库不成熟/质量差,我不希望您让联盟使用它。我建议找一个不同/更好的肥皂库。
  • @MattC 感谢您的评论。很高兴了解 WSDL,但希望肥皂库不是问题(它是原生 PHP 库)。我检查了 nuSoap,但看起来它没有任何优势。
  • 我真的不想听起来刻薄,@ShaneN,但是内置到 PHP 中并不能保证质量。参见例如蹩脚的mail()。没有使用 PHP 的 SOAP,所以我无能为力。
  • 我试图至少通过编辑问题以使其更易于阅读来提供帮助。请将代码截图替换为带有实际代码的代码块。将代码发布为屏幕截图可以防止其他人摆弄它。

标签: php web-services wcf soap


【解决方案1】:
  1. 您可以将此 URL 用于 WSDL https://slc.centershift.com/Sandbox40/StoreService.svc?singleWsdl。此 WSDL 包含所有定义。

  2. 您必须使用 1.2,因为此 Web 服务适用于 SOAP 1.2 版本。我用 1.1 和 1.2 试了一下,都报错了。 1.1是版本错误,1.2是超时错误。我认为此测试服务器存在错误。我将它与 svcutil 一起使用来生成代码,但它也给出了错误。通常它应该获取信息并生成代码示例来调用服务。

  3. 通常您可以使用 SoapHeader 添加身份验证参数或直接添加到 SoapClient 构造中的选项(如果服务身份验证是基本身份验证)。我根据您的屏幕截图编写以下代码。但长时间等待后它会超时。

    $wsdl = "https://slc.centershift.com/sandbox40/StoreService.svc?wsdl";
    $client = new SoapClient($wsdl,array('trace' => 1,'soap_version'   => SOAP_1_2));
    
    $security = array(
    'UserName' => array(
        'UserName'=>'TestUser',
        'Password'=>'TestPassword',
        'SupportInteractive'=>false
     )
    );
    
    $header = new SoapHeader('ChannelFactory','Credentials',$security, false);
    $client->__setSoapHeaders($header);
    
    
    
    $params = array();
    $params['SiteID'] = 100000000;
    $params['Channel'] = 999;
    try {
        $ret = $client->GetSiteUnitData($params);
        print_r($ret);
    }catch(Exception $e){
      echo $e->getMessage();
    }
    

    __getFunctions 有效,因为它打印 WSDL 中定义的函数。在第一次调用时获取 WSDL 信息没有问题。但真正的问题是沟通。 PHP 获取 WSDL,生成所需的 SOAP 请求然后发送到服务器,但服务器没有正确响应。即使参数或请求正文不正确,SOAP 服务器也会始终给出响应。

    您应该与服务提供商沟通,我认为他们可以明确回答您的问题。

【讨论】:

  • 非常感谢您的回复。不幸的是,服务提供商不愿意提供帮助。他们声称他们的服务适用于 .NET 客户端,因此他们没有理由调查它不适用于任何其他客户端类型。从本质上讲,他们迫使我们使用 Microsoft 堆栈,而我们不会只为他们这样做。
【解决方案2】:

在使用 PHP 中的 .NET WS 之前,我相信您需要从 PHP 中的类创建与 .NET 期望的名称相匹配的对象。 WSDL 应该告诉您它所期望的类型。我希望这有助于您前进!

【讨论】:

    【解决方案3】:

    如果 SOAP 调用来自 C# 应用程序,您可以使用 Wireshark(使用过滤器 ip.dst == 204.246.130.80)查看正在发出的实际请求,然后从 php 构造类似的请求。

    查看this answer 了解如何进行自定义 SOAP 调用。

    还可以选择执行原始 curl 请求,因为构建 xml 正文可能更容易,但您必须自己使用 simplexml 解析响应。

    【讨论】:

    • 我试过了,但是请求都是通过 SSL 完成的,所以消息的任何负载都被加密了。有一种加载证书的方法,以便您可以解密它,我尝试过,但对我不起作用(我想我需要他们的私钥,我没有)
    • 如果它在http连接上不起作用,那么查看数据包的最简单方法是为连接设置代理并使用Fiddler作为代理来捕获和查看数据。
    猜你喜欢
    • 1970-01-01
    • 2019-09-14
    • 2013-09-23
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2012-02-13
    • 1970-01-01
    相关资源
    最近更新 更多