使用PHP调用WCF服务(具有联合安全性)

Sha*_*e N 19 php wcf soap web-services

我正在尝试从PHP调用WCF服务(.NET).它比使用a更复杂,SoapClient因为服务使用a 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);
Run Code Online (Sandbox Code Playgroud)
  1. 我应该指向哪个WSDL?

  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标头?或者我认为这一切都错了,我甚至需要在调用方法之前进行某种身份验证(从我读到的内容来看,我应该得到一个令牌,然后将其用于所有未来的方法调用 - 我我认为我在Stack Overflow的答案中看到了这个例子.

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

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

我已经阅读了如何:在MSDN上创建WSFederationHttpBinding,但它没有帮助.

小智 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();
    }
    
    Run Code Online (Sandbox Code Playgroud)

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

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