的内置PHP
扩展SOAP
不会验证传入SOAP
请求中的所有内容XML Schema
与WSDL
. 它确实会检查基本实体的存在,但是当你有一些复杂的东西比如simpleType
限制时,扩展几乎会忽略它们的存在。
验证包含在中的SOAP
请求的最佳方法是什么?XML Schema
WSDL
除了原生 PHP5 SOAP 库之外,我还可以告诉您,目前 PEAR 和 Zend SOAP 库都不会对消息进行模式验证。(不幸的是,我不知道有任何 PHP SOAP 实现。)
我要做的是将 XML 消息加载到DOMDocument对象中,并使用 DOMDocument 的方法来验证架构。
在这个问题上一直在挖掘一个视图时间。本机 PHP SoapServer 和 NuSOAP 库都不进行任何验证。PHP SoapServer 只是进行类型转换。例如,如果您定义
<xsd:element name="SomeParameter" type="xsd:boolean" />
并提交
<get:SomeParameter>dfgdfg</get:SomeParameter>
你会得到 php 类型 boolean (true)
尽管 NuSOAP 识别简单类型,但它只是将所有内容转换为字符串:
从 nuSOAP 调试日志:
nusoap_xmlschema: processing typed element SomeParameter of type http://www.w3.org/2001/XMLSchema:boolean
所以最好的方法是 joelhardi 解决方案来验证自己或使用一些 xml 解析器,如 XERCES
通常不会根据 WSDL 进行验证。如果 WSDL 设计正确,则应该有一个底层 xml 模式 (XSD) 来验证请求的正文。您的 XML 解析器应该能够做到这一点。
其余的取决于您如何实现 Web 服务以及您使用的 SOAP 引擎。我不直接熟悉 PHP 引擎。对于 WSDL/接口级别的“验证”,我通常会这样做:
使用本机 SoapServer PHP有点棘手,但也可以:
function validate(string $xmlEnvelope, string $wsdl) : ?array{
libxml_use_internal_errors(true);
//extracting schema from WSDL
$xml = new DOMDocument();
$wsdl_string = file_get_contents($wsdl);
//extracting namespaces from WSDL
$outer = new SimpleXMLElement($wsdl_string);
$wsdl_namespaces = $outer->getDocNamespaces();
//extracting the schema tag inside WSDL
$xml->loadXML($wsdl_string);
$xpath = new DOMXPath($xml);
$xpath->registerNamespace('xsd', 'http://www.w3.org/2001/XMLSchema');
$schemaNode = $xpath->evaluate('//xsd:schema');
$schemaXML = "";
foreach ($schemaNode as $node) {
//add namespaces from WSDL to schema
foreach($wsdl_namespaces as $prefix => $ns){
$node->setAttribute("xmlns:$prefix", $ns);
}
$schemaXML .= simplexml_import_dom($node)
->asXML();
}
//capturing de XML envelope
$xml = new DOMDocument();
$xml->loadXML($xmlEnvelope);
//extracting namespaces from soap Envelope
$outer = new SimpleXMLElement($xmlEnvelope);
$envelope_namespaces = $outer->getDocNamespaces();
$xpath = new DOMXPath($xml);
$xpath->registerNamespace('soapEnv', 'http://schemas.xmlsoap.org/soap/envelope/');
$envelopeBody = $xpath->evaluate('//soapEnv:Body/*[1]');
$envelopeBodyXML = "";
foreach ($envelopeBody as $node) {
//add namespaces from envelope to the body content
foreach($envelope_namespaces as $prefix => $ns){
$node->setAttribute("xmlns:$prefix", $ns);
}
$envelopeBodyXML .= simplexml_import_dom($node)
->asXML();
}
$doc = new DOMDocument();
$doc->loadXML($envelopeBodyXML); // load xml
$is_valid_xml = $doc->schemaValidateSource($schemaXML); // path to xsd file
return libxml_get_errors();
}
在您的 SoapServer 函数实现中:
function myFunction($param) {
$xmlEnvelope = file_get_contents("php://input");
$errors = validate($xmlEnvelope, $wsdl);
}
我找不到任何简单的方法来执行验证,最终在业务逻辑中有验证代码。
前段时间,我使用NuSOAP创建了一个使用 PHP 的概念验证Web 服务。我不知道它是否验证了输入,但我认为它确实如此。