web 调用 php_从PHP调用安全的Web服务方法

web 调用 php

在你开始前

目标

本教程将为您提供:

  • PHP中的SOAP概述
  • 通过实际的实现示例演示如何创建安全标头
  • 描述可能作为参数传递给SOAP方法的复杂结构,以及如何将此类参数PHP表示形式转换为SOAP调用参数的所需格式

先决条件

本教程假定您具有PHP5脚本语言的基本知识。 对于安装PHP和PHP SOAP扩展的,请参考文章“访问企业应用程序从PHP脚本”,在列出的相关主题

系统要求

要运行本教程中的示例,您需要:

  • 任何Web浏览器,最好是MS IE 4.0或更高版本或Mozilla Firefox 1.0或更高版本
  • 安装了任何HTTP服务器和PHP 5扩展的前端计算机
  • 任何支持Web服务接口(WSDL,HTTP上的SOAP)并实现基本WS-Security协议的服务器

入门

开源应用程序和开放标准正成为在Web上构建应用程序的首选方法。 创建此类应用程序的最有效方法是利用Web上现有的软件组件和服务。 这种分层应用程序的常见实现包括使用Web服务的服务器端PHP脚本。 使用这种类型的体系结构,对安全通信的需求日益增长。

SOAP和PHP-概述和参考

在引入PHP 5之前,很难用纯PHP调用Web服务。 在PHP 5中,应用程序开发人员具有许多用于实现PHP Web服务客户端的选项:PEAR:SOAP,NuSOAP和新的SOAP扩展。 本教程重点介绍后者的用法。

与以前PHP解决方案相比,SOAP扩展具有改进的功能,包括SoapVar类型和几种可用于构造几乎任何复杂SOAP类型的OO机制。

根据Rosenberg和Remy在2005年的书(请参阅参考资料 ),“ WS-Security是一个总体概念模型,将不同的安全技术抽象为“ claims”和“ tokens” ... SOAP标头用于指令信息。 SOAP安全性存在的地方;用于管理和保护消息的系统级信息也放置在这里; SOAP运行时和中介处理SOAP标头指令;标头旨在添加新的特性和功能; WS-Security标头将位于此处。发送方可以要求接收方理解标头,标头直接与SOAP处理器对话,如果不理解标头,则可以要求处理器拒绝整个SOAP消息。不了解,您可能根本不希望它处理此SOAP消息。”

developerWorks文章从PHP脚本访问企业应用程序 (请参阅参考资料 )描述了PHP 5中SOAP在使用Web服务访问J2EE应用程序中的用法。 它还描述了SOAP PHP安装过程,并与我们在此处讨论的安全性问题有关。 文章指出:“ ...在ext / soap中没有对WS-Security的一流支持。因此,如果我们要在PHP中发送和接收WS-Security标头,则必须将其放入更详细的接口,我们可以在其中明确创建SOAP标头。...您可以使用SoapHeader, SoapParam and SoapVar类来构建消息元素,然后使用SoapClient::__call来发送SOAP请求并获得响应。”

创建一个WS-Security标头

如上所述,WS-Security通过将安全标头添加到SOAP消息中来工作。 下面的框列出了WS-Security基本身份验证所需的安全标头的示例(用户myUserName和密码myPass):

清单1. WS-Security基本身份验证的安全标头
<soapenv:Header xmlns:soapenv="http://schemas.xmlsoap.org/soap/envelope/">
  <wsse:Security xmlns:wsse="http://schemas.xmlsoap.org/ws/2003/06/secext">
    <wsse:UsernameToken>
      <wsse:Username>myUserName</wsse:Username>
      <wsse:Password>myPass</wsse:Password>
    </wsse:UsernameToken>
  </wsse:Security>
</soapenv:Header>

这里的挑战是利用通用的SOAP扩展对象构造来创建所需的标头并将它们集成到SOAP调用中。 用于此任务的工具是SOAP扩展的SoapVar数据结构,该结构在PHP在线手册中定义(请参阅参考资料 ):

SoapVar是一个特殊的低级类,用于在非WSDL模式下编码参数和返回值。它只是一个数据持有者,除了构造函数外,没有任何其他特殊方法。当您要在其中设置type属性时,它很有用。 SOAP请求或响应。​​构造函数获取要传递或返回的数据,使用编码ID对其进行编码(在本例中为SOAP_VAR_ENC ),还可以选择键入名称,类型名称空间,节点名称和节点名称名称空间。”

创建所需的嵌套标签的过程是:将UsernamePassword简单(即,无嵌套)标签包装到SoapVar 。 然后,应将结果包装到另一个标记为UsernameToken SoapVar ,将其放置在<Security>标记内。 最后,此标记放置在SOAP标头中。

在这种情况下,所需的包装操作深度为两层。 通常,这里描述的方法也可以应用于创建任意嵌套级别的复杂SOAP对象。

在下一节中,我们将描述实际的实现。

用PHP编码基本安全性

SOAP标头的Security标签使用自底向上方法进行组装。 首先,UserName和Password标记表示为XSD字符串。 清单2假设正确分配了$ username和$ password变量:

清单2.从凭据创建XSD字符串
$nameSpace = "http://schemas.xmlsoap.org/ws/2003/06/secext";//WS-Security namespace
$userT = new SoapVar($username, XSD_STRING, NULL, $nameSpace, NULL, $nameSpace);
$passwT = new SoapVar($password, XSD_STRING, NULL, $nameSpace, NULL, $nameSpace);

为了用嵌套的<Username>和<Password>标记表示<UserNameToken>标记,我们需要定义带有私有数据成员的中间类: $Username$Password 。 请注意,尽管已定义的类可以具有任意名称,但是数据成员必须具有与相应XML标记相同的名称。 我们的实现创建一个名为UsernameT1的类。 数据成员由构造函数分配。

清单3. UsernameT1类定义
class UsernameT1 {
 private $Username; //Name must be  identical to corresponding XML tag in SOAP header
 private $Password; // Name must be  identical to corresponding XML tag in SOAP header 
 function __construct($username, $password) {
	$this->Username=$username;
	$this->Password=$password;
      }
}

现在,我们可以将复杂XML标签<UsernameToken>的内容创建为SoapVar ,其类型不是XSD_STRING ,而是SOAP_ENC_OBJECT 。 在这种情况下(与创建XSD字符串不同),创建的XML标签的名称也将传递给SoapVar构造函数。

清单4.创建一个UserNameT1实例并将其包装到SoapVar中
$tmp = new UsernameT1($userT, $passwT);
$uuT = new SoapVar($tmp, SOAP_ENC_OBJECT, NULL, $nameSpace, 'UsernameToken', $nameSpace);

SoapVar将与私有数据成员$UsernameToken一起包装到UserNameT2类中。 同样,已定义的类可以具有任意名称,但是数据成员必须与相应的XML标记具有相同的名称。

清单5. UsernameT2类定义
class UserNameT2 {
  private $UsernameToken;  
  //Name must be  identical to corresponding XML tag in SOAP header
  function __construct ($innerVal){
		$this->UsernameToken = $ innerVal;
  }
}

创建一个UserNameT2实例并将其包装到SoapVar

清单6.创建一个UserNameT2实例并将其包装到SoapVar中
$tmp = new UsernameT2($uuT);
$userToken = new SoapVar($tmp, SOAP_ENC_OBJECT, NULL, $nameSpace, 
 'UsernameToken', $nameSpace);

再次使用相同的方法,将UsernameToken对象附加到父<Security> XML标记,并且现在构造了SoapHeader <Security>:

清单7.限制安全头
$secHeaderValue=new SoapVar($userToken, SOAP_ENC_OBJECT, NULL, $nameSpace, 
                    'Security', $nameSpace);
$secHeader = new SoapHeader($nameSpace, 'Security', $secHeaderValue);

此标头将作为input_headers数组中的元素传递到SoapClient类的__soapCall()方法。 例如,当安全性是唯一的输入标头时:

清单8.使用安全标头
$client->__soapCall($theMethodName, $theMethodSignature, null, $secHeader );

创建方法的签名

调用__soapCall包括一项附加任务:方法传递参数的构造,也称为方法签名。 对于简单的参数列表,这是一项琐碎的任务,已在PHP在线手册中进行了记录(请参阅参考资料 )。 本节处理更复杂的情况,其中Web服务的方法包括数组和对象参数,并且这些参数也可能具有本身就是数组或对象的成员。

与安全标头一样,我们需要使用SOAP扩展的SoapVar数据结构来创建嵌套标签。 这是作为对象的每个参数以及任何传递的数组或对象的每个对象成员所必需的。

下一节将介绍一些方法,这些方法可以将一组复杂的参数__soapCall到有效的__soapCall arguments参数中。

用PHP编写方法签名

本节列出了用于将PHP参数打包到SOAP调用中的代码。 为此,需要输入的通用定义。 我们已将输入定义为PHP参数数组。 数组可以包括简单类型,对象,数组,嵌套对象和嵌套数组。

例如,考虑一种获得三个参数的Web服务方法storeProblemReport()的情况:严重性(整数),错误(字符串数组)和所有者(具有成员的记录,该记录也是记录)。 这种方法的WSDL部分可能包含以下几行:

清单9.示例方法和参数-WSDL定义
<xsd:complexType name="fileInfo">
 <xsd:sequence>
  <xsd:element name="fname" type="xsd:string"/>
  <xsd:element name="line" type="xsd:int"/>
 </xsd:sequence>
</xsd:complexType>
<xsd:complexType name="ownerInfo">
 <xsd:sequence>
  <xsd:element name="component" type="xsd:string"/>
  <xsd:element name="location" type="intf:fileInfo"/>
 </xsd:sequence>
</xsd:complexType>
<xsd:element name="storeProblemReport">
  <xsd:complexType>
   <xsd:sequence>
    <xsd:element name="severity" type="xsd:int"/>
    <xsd:element name="errors" type="xsd:string" minOccurs="0" maxOccurs="unbounded"/>
    <xsd:element name="owner" type="intf:ownerInfo"/>
   </xsd:sequence>
  </xsd:complexType>
</xsd:element>

可能值和值输入的示例可能是:

清单10.分配示例参数
$fileInfo->fname = '/usr/src/myDir/getToken.php'
$fileInfo->line = 7;
$theOwner->component = 'Parser';
$theOwner->location = $fileInfo;
$argumentsList = array ('severity'=> 7,
                        'errors' => array ("empty token","read error", "File open error"),
                        'owner'=> $theOwner));

通过下面的CreateMethodSignature()函数可以为soapCall创建所需的参数:

清单11.创建所需的参数
function createMethodSignature($theMethod, $paramAr) {
    if (null == $paramAr) 
        return array($theMethod =>null);
    $used = null;
    foreach ($paramAr as $name => $value) {
           if (is_array($value) || is_object($value)) {
               $used[$name] = createMixedValueSignature($value);
           } else {
               $used[$name] =  $value;
           }
   }
   return array($theMethod =>$used);
}
//---------------------------------------------------------------------
// inner routine: packing an inner complex parameter into a  SOAP-valid representation 
function createMixedValueSignature($MixedVals) {
    $mixedParamsList = null;
    if (is_object($MixedVals)) {
        foreach ($MixedVals as $name => $value) {
              if (is_object($value) || is_array($value)) {
               $mixedParamsList->$name = createMixedValueSignature($value);
          } else {
            $mixedParamsList->$name = $value;
          }
        }
        // an object needs to be passed as SoapVar
        return new SoapVar($mixedParamsList, SOAP_ENC_OBJECT , NULL, NULL);
    } else { // an array
        foreach ($MixedVals as $name => $value) {
           if (is_object($value) || is_array($value)) {
             $mixedParamsList[$name] = createMixedValueSignature($value);
           } else {
             $mixedParamsList[$name] = $value;
           }
        }
        // an array is passed as is !!
        return $mixedParamsList;
    }
}

请注意,简单数据类型的数组或数组(不包含对象的数组)不需要特殊处理。 使用递归函数createMixedValueSignature()处理数组的唯一原因是内部PHP对象的可能性。 具有上述输入的CreateMethodSignature()用于产生有效的SOAP参数:

清单12.调用示例方法
$theMethodSignature = CreateMethodSignature('storeProblemReport', $argumentsList);
$client->__soapCall('storeProblemReport', $theMethodSignature, null, $secHeader );

摘要

本教程展示了如何使用PHP 5的SOAP扩展实现WS-Security基本身份验证方案以及如何传递复杂的参数。我们仅介绍了WS-Security规范的一小部分。 为了提供全面的WS-Security,应该实施更复杂(更严格)的身份验证方案,例如X.509,以及WS-Security中的许多其他元素,例如XML加密和XML签名。功能。 关于将PHP结构化参数处理为SOAP参数的示例,此处的示例是通用示例,旨在用于一系列复杂参数。 该列表可能包括嵌套的对象和数组。 可以轻松修改此示例以适合任何特定且更简单的用法。


翻译自: https://www.ibm.com/developerworks/webservices/tutorials/ws-soa-callsecurephp/ws-soa-callsecurephp.html

web 调用 php

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值