Reputation: 6962
The built-in PHP
extension for SOAP
doesn't validate everything in the incoming SOAP
request against the XML Schema
in the WSDL
. It does check for the existence of basic entities, but when you have something complicated like simpleType
restrictions the extension pretty much ignores their existence.
What is the best way to validate the SOAP
request against XML Schema
contained in the WSDL
?
Upvotes: 12
Views: 12459
Reputation: 402
Using native SoapServer PHP is a little bit tricky but is possible too:
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();
}
and inside your SoapServer function implementation:
function myFunction($param) {
$xmlEnvelope = file_get_contents("php://input");
$errors = validate($xmlEnvelope, $wsdl);
}
Upvotes: 2
Reputation: 46
Been digging around on this matter a view hours. Neither the native PHP SoapServer nore the NuSOAP Library does any Validation. PHP SoapServer simply makes a type cast. For Example if you define
<xsd:element name="SomeParameter" type="xsd:boolean" />
and submit
<get:SomeParameter>dfgdfg</get:SomeParameter>
you'll get the php Type boolean (true)
NuSOAP simply casts everthing to string although it recognizes simple types:
from the nuSOAP debug log:
nusoap_xmlschema: processing typed element SomeParameter of type http://www.w3.org/2001/XMLSchema:boolean
So the best way is joelhardi solution to validate yourself or use some xml Parser like XERCES
Upvotes: 3
Reputation: 6962
I was not able to find any simple way to perform the validation and in the end had validation code in the business logic.
Upvotes: -1
Reputation: 11179
Besides the native PHP5 SOAP libs, I can also tell you that neither the PEAR nor Zend SOAP libs will do schema validation of messages at present. (I don't know of any PHP SOAP implementation that does, unfortunately.)
What I would do is load the XML message into a DOMDocument object and use DOMDocument's methods to validate against the schema.
Upvotes: 4
Reputation: 13118
Some time ago I've create a proof of concept web service with PHP using NuSOAP. I don't know if it validates the input, but I would assume it does.
Upvotes: -3
Reputation: 292
Typically one doesn't validate against the WSDL. If the WSDL is designed properly there should be an underlying xml schema (XSD) to validate the body of the request against. Your XML parser should be able to do this.
The rest is up to how you implement the web service and which SOAP engine you are using. I am not directly familiar with the PHP engine. For WSDL/interface level "validation" I usually do something like this:
Upvotes: 2