如何在php5中实现ws-security 1.1
我试图在PHP5中使用Soap调用Web服务,为此,我需要使用WS-Security 1.1 (在java和.NET中,这都是自动生成的。) 是否有任何框架可以在PHP中轻松生成安全头?还是我必须自己添加整个标题 WS-Security 1.1的规范:在上,Roger Veciana i Rovira提交了以下内容(我刚刚重新格式化了代码):如何在php5中实现ws-security 1.1,php,web-services,zend-framework,soap,ws-security,Php,Web Services,Zend Framework,Soap,Ws Security,我试图在PHP5中使用Soap调用Web服务,为此,我需要使用WS-Security 1.1 (在java和.NET中,这都是自动生成的。) 是否有任何框架可以在PHP中轻松生成安全头?还是我必须自己添加整个标题 WS-Security 1.1的规范:在上,Roger Veciana i Rovira提交了以下内容(我刚刚重新格式化了代码): 类WSSoapClient扩展了SoapClient{ 私有$username; 私人$password; /*生成安全标头*/ 私有函数wssecuri
类WSSoapClient扩展了SoapClient{
私有$username;
私人$password;
/*生成安全标头*/
私有函数wssecurity_header(){
/*时间戳。计算机必须准时或您所在的服务器
*为了安全起见,连接可能会拒绝密码摘要。
*/
$timestamp=gmdate('Y-m-d\TH:i:s\Z');
/*一个随机词。如果服务器不可用,则使用rand()可能会重复该词
*负载很重。
*/
$nonce=mt_rand();
/*这是创建密码摘要的正确方法
*直接使用密码也可以,但传输它并不安全
*没有加密。无论如何,至少在axis+wss4j中,nonce
*无论如何,时间戳都是必需的。
*/
$passdigest=base64\u编码(
包装('H*',
沙一(
pack('H*',$nonce).pack('a*',$timestamp)。
打包('a*',$this->password));
$auth='1
“.$this->username。”
“.$passdigest。”
“.base64_编码(pack('H*',$nonce))。”
“.$timestamp。”
';
/*XSD_ANYXML(或147)是将xml直接添加到SoapVar中的代码。
*使用其他代码,如SOAP_ENC,设置
*请更正变量的命名空间,以便axis服务器拒绝
*xml。
*/
$authvalues=newsoapvar($auth,XSD_ANYXML);
$header=新的SoapHeader(“http://docs.oasis-open.org/wss/2004/01/oasis-".
“200401-wss-wssecurity-secext-1.0.xsd”、“安全性”、$authvalues、,
正确的);
返回$header;
}
/*如果要设置不同的用户,则必须调用它
*密码
*/
公共函数\uuuu setUsernameToken($username,$password){
$this->username=$username;
$this->password=$password;
}
/*覆盖添加安全标头的原始方法
*请参见,如果要添加更多标题,则需要修改该方法
*/
公共函数\uuuSOAPCALL($function\u name,$arguments,$options=null,
$input\u headers=null,$output\u headers=null){
$result=parent::uu soapCall($function\u name,$arguments,$options,
$this->wssecurity_header());
返回$result;
}
}
我注意到这是针对1.0版的,但希望它能让您走上正轨。感谢您的回复,现在我得到了下一个异常Uncaught SoapFault异常:[HTTP]无法处理邮件,因为内容类型为“text/xml;charset=utf-8“不是预期的类型”application/soap+xml;字符集=utf-8'。在/home/projects/caheritage/site/providence/app/lib/core/WSSoapClient.php:80中,您知道如何解决这个问题吗?wsHttpBinding(SOAP 1.2)使用“application/SOAP+xml”内容类型,basicHttpBinding(SOAP 1.1)使用“text/xml”,因此请确保您的php和WCF匹配。ie-在WCF中调用basic或ws绑定时,确保PHP设置为使用正确的SOAP版本
class WSSoapClient extends SoapClient {
private $username;
private $password;
/*Generates de WSSecurity header*/
private function wssecurity_header() {
/* The timestamp. The computer must be on time or the server you are
* connecting may reject the password digest for security.
*/
$timestamp = gmdate('Y-m-d\TH:i:s\Z');
/* A random word. The use of rand() may repeat the word if the server is
* very loaded.
*/
$nonce = mt_rand();
/* This is the right way to create the password digest. Using the
* password directly may work also, but it's not secure to transmit it
* without encryption. And anyway, at least with axis+wss4j, the nonce
* and timestamp are mandatory anyway.
*/
$passdigest = base64_encode(
pack('H*',
sha1(
pack('H*', $nonce) . pack('a*',$timestamp).
pack('a*',$this->password))));
$auth = '
<wsse:Security SOAP-ENV:mustUnderstand="1" xmlns:wsse="http://docs.oasis-open.'.
'org/wss/2004/01/oasis-200401-wss-wssecurity-secext-1.0.xsd">
<wsse:UsernameToken>
<wsse:Username>'.$this->username.'</wsse:Username>
<wsse:Password Type="http://docs.oasis-open.org/wss/2004/01/oasis-200401-'.
'wss-username-token-profile-1.0#PasswordDigest">'.$passdigest.'</wsse:Password>
<wsse:Nonce>'.base64_encode(pack('H*', $nonce)).'</wsse:Nonce>
<wsu:Created xmlns:wsu="http://docs.oasis-open.org/wss/2004/01/oasis-'.
'200401-wss-wssecurity-utility-1.0.xsd">'.$timestamp.'</wsu:Created>
</wsse:UsernameToken>
</wsse:Security>
';
/* XSD_ANYXML (or 147) is the code to add xml directly into a SoapVar.
* Using other codes such as SOAP_ENC, it's really difficult to set the
* correct namespace for the variables, so the axis server rejects the
* xml.
*/
$authvalues = new SoapVar($auth,XSD_ANYXML);
$header = new SoapHeader("http://docs.oasis-open.org/wss/2004/01/oasis-".
"200401-wss-wssecurity-secext-1.0.xsd", "Security", $authvalues,
true);
return $header;
}
/* It's necessary to call it if you want to set a different user and
* password
*/
public function __setUsernameToken($username, $password) {
$this->username = $username;
$this->password = $password;
}
/* Overwrites the original method adding the security header. As you can
* see, if you want to add more headers, the method needs to be modifyed
*/
public function __soapCall($function_name, $arguments, $options=null,
$input_headers=null, $output_headers=null) {
$result = parent::__soapCall($function_name, $arguments, $options,
$this->wssecurity_header());
return $result;
}
}