我需要在我的SoapClient标头中添加以下具有不同名称空间和类型的复杂标头。
<soapenv:Header xmlns:wsa="http://www.w3.org/2005/08/addressing">
<wsse:Security soapenv:mustUnderstand="1" xmlns:wsse="http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-wssecurity-secext-1.0.xsd" xmlns:wsu="http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-wssecurity-utility-1.0.xsd">
<wsse:UsernameToken>
<wsse:Username>****</wsse:Username>
<wsse:Password Type="http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-username-token-profile-1.0#PasswordText">*****</wsse:Password>
</wsse:UsernameToken>
</wsse:Security>
<wsa:Action>/IntS5/S5WS</wsa:Action>
</soapenv:Header>
其他答案中提出的我尝试了PHP项目中的以下方法。由于我需要WSA,我将WSA:与安全标头一起设置了操作。
$header_part = '<wsse:Security soapenv:mustUnderstand="1" xmlns:wsse="http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-wssecurity-secext-1.0.xsd" xmlns:wsu="http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-wssecurity-utility-1.0.xsd">'
. '<wsse:UsernameToken><wsse:Username>****</wsse:Username><wsse:Password Type="http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-username-token-profile-1.0#PasswordText">****</wsse:Password>'
. '</wsse:UsernameToken></wsse:Security><wsa:Action>/IntS5/S5WS</wsa:Action>';
$soap_var_header = new SoapVar($header_part, XSD_ANYXML, null, null, null);
$soap_header = new SOAPHeader('http://www.w3.org/2005/08/addressing', 'wsa', $soap_var_header);
$client->__setSoapHeaders($soap_header);
一些__SOAPCALL如何返回我以下错误。
soapfault异常:[客户端] dtd不受SOAP的支持。我不确定它是否与标头或putCall的参数有关。有人可以帮助我吗?
编辑:问题可能与标题/信封的名称空间有关。
发送到服务器的请求看起来像这样。更新
<?xml version="1.0" encoding="UTF-8"?>
<env:Envelope xmlns:env="http://www.w3.org/2003/05/soap-envelope" xmlns:ns1="http://ws.s5.mediasat.de/" xmlns:ns2="http://www.w3.org/2005/08/addressing">
<env:Header>
<wsse:Security 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>****</wsse:Username>
<wsse:Password Type="http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-username-token-profile-1.0#PasswordText">*****</wsse:Password>
</wsse:UsernameToken>
</wsse:Security>
<wsa:Action xmlns:wsa="http://www.w3.org/2005/08/addressing">/IntS5/S5WS</wsa:Action>
</env:Header>
<env:Body>
<ns1:putCall>
<transaction>createIncident</transaction>
<transactionSender>Request</transactionSender>
<caseDataModel>
<senderId>7</senderId>
<ticketTypeId>102</ticketTypeId>
<title>test</title>
<priorityId>101</priorityId>
<categoryId>128</categoryId>
<description>Description</description>
<ticketNumberSender>INCC00000743809</ticketNumberSender>
<createTypeId>701</createTypeId>
<serviceId>B001APP05K</serviceId>
<categoryId>128</categoryId>
<serviceRecipientId>77888</serviceRecipientId>
<serviceLocationSAPCode>V135</serviceLocationSAPCode>
</caseDataModel>
</ns1:putCall>
</env:Body>
</env:Envelope>
在SOAP UI上有效的请求
<soapenv:Envelope xmlns:soapenv="http://schemas.xmlsoap.org/soap/envelope/" xmlns:ws="http://ws.s5.mediasat.de/">
<soapenv:Header xmlns:wsa="http://www.w3.org/2005/08/addressing">
<wsse:Security soapenv:mustUnderstand="1" xmlns:wsse="http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-wssecurity-secext-1.0.xsd" xmlns:wsu="http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-wssecurity-utility-1.0.xsd">
<wsse:UsernameToken>
<wsse:Username>***</wsse:Username>
<wsse:Password Type="http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-username-token-profile-1.0#PasswordText">***</wsse:Password>
</wsse:UsernameToken>
</wsse:Security>
<wsa:Action>/IntS5/S5WS</wsa:Action>
</soapenv:Header>
<soapenv:Body>
<ws:putCall>
<transaction>createIncident</transaction>
<transactionSender>Request</transactionSender>
<caseDataModel>
<senderId>7</senderId>
<ticketTypeId>102</ticketTypeId>
<title>test</title>
<priorityId>101</priorityId>
<categoryId>128</categoryId>
<description>Description</description>
<ticketNumberSender>INCC00000743809</ticketNumberSender>
<createTypeId>701</createTypeId>
<serviceId>B001APP05K</serviceId>
<categoryId>128</categoryId>
<serviceRecipientId>77888</serviceRecipientId>
<serviceLocationSAPCode>V135</serviceLocationSAPCode>
</caseDataModel>
</ws:putCall>
</soapenv:Body>
</soapenv:Envelope>
无论如何是否有设置/覆盖标题的名称空间?
您应该通过程序生成标头,而不是使用字符串。
示例:
<?php
$client = new SoapClient(null, array(
'location' => "http://localhost/soap/",
'uri' => "http://ws.s5.mediasat.de/",
'soap_version' => SOAP_1_2
));
$username = '***';
$password = '***';
$sec_namespace = 'http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-wssecurity-secext-1.0.xsd';
$wsa_namespace = 'http://www.w3.org/2005/08/addressing';
// prepare security token
$node1 = new SoapVar($username, XSD_STRING, null, null, 'Username', $sec_namespace);
$xml = new XMLWriter(); // this is a little hacky, but no other way to set the type as far as I know
$xml->openMemory();
$xml->startElementNS('wsse', 'Password',$sec_namespace);
$xml->writeAttribute('Type', 'http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-username-token-profile-1.0#PasswordText');
$xml->Text($password);
$xml->endElement();
$node2 = new SoapVar($xml->outputMemory(), XSD_ANYXML);
$token = new SoapVar(array($node1, $node2), SOAP_ENC_OBJECT, null, null, 'UsernameToken', $sec_namespace);
$security = new SoapVar(array($token), SOAP_ENC_OBJECT, null, null, 'Security', $sec_namespace);
$soap_header_sec = new SOAPHeader($sec_namespace, 'Security', $security, true);
// prepare action token
$action = new SoapVar('/IntS5/S5WS', XSD_STRING, null, null, 'Action', $wsa_namespace);
$soap_header_action = new SOAPHeader($wsa_namespace, 'Action', $action, false);
// set prepared headers
$client->__setSoapHeaders(
[$soap_header_sec,$soap_header_action]
);
$client->putCall();
这将产生有效的信封,并设置所有名称空间:
<?xml version="1.0" encoding="utf-8"?>
<env:Envelope xmlns:env="http://www.w3.org/2003/05/soap-envelope" xmlns:ns1="http://ws.s5.mediasat.de/" xmlns:ns2="http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-wssecurity-secext-1.0.xsd" xmlns:ns3="http://www.w3.org/2005/08/addressing" xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns:enc="http://www.w3.org/2003/05/soap-encoding">
<env:Header>
<ns2:Security env:mustUnderstand="true">
<ns2:UsernameToken>
<ns2:Username>***</ns2:Username>
<wsse:Password Type="http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-username-token-profile-1.0#PasswordText" xmlns:wsse="http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-wssecurity-secext-1.0.xsd">***</wsse:Password>
</ns2:UsernameToken>
</ns2:Security>
<ns3:Action>/IntS5/S5WS</ns3:Action>
</env:Header>
<env:Body>
<ns1:putCall env:encodingStyle="http://www.w3.org/2003/05/soap-encoding" />
</env:Body>
</env:Envelope>
-
名称space" http://www.w3.org/2005/08/addressing"不绑定到前缀" WSA"。
-
" Musdunderand"属性必须使用前缀" env"不是" soapenv"。
您可以在本地声明缺少的名称空间。您只需要修复header_part即可看起来像这样:
header_part = '<wsse:Security env:mustUnderstand="1" xmlns:wsse="http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-wssecurity-secext-1.0.xsd" xmlns:wsu="http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-wssecurity-utility-1.0.xsd">'
. '<wsse:UsernameToken><wsse:Username>****</wsse:Username><wsse:Password Type="http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-username-token-profile-1.0#PasswordText">****</wsse:Password>'
. '</wsse:UsernameToken></wsse:Security><wsa:Action xmlns:wsa="http://www.w3.org/2005/08/addressing">/IntS5/S5WS</wsa:Action>';
注意:也许很明显,但是假设" http://www.w3.org/2003/05/05/soap-envelope的前缀"总是有点危险成为" env"。该框架可以随时更改。如果您想站在真正安全的一面,则可能更喜欢将本地命名空间绑定到新的前缀:
<wsse:Security soapenv:mustUnderstand="1" xmlns:soapenv="http://www.w3.org/2003/05/soap-envelope" ...
但是,一个名称空间绑定到两个不同的前缀会使事情更难阅读和理解,所以我会说这是一个品味的问题。