Glenn Moss
Glenn Moss

Reputation: 6962

Validate an incoming SOAP request to the WSDL in PHP

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

Answers (6)

celsowm
celsowm

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

CodeKid
CodeKid

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

Glenn Moss
Glenn Moss

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

joelhardi
joelhardi

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

Grey Panther
Grey Panther

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

user11087
user11087

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:

  1. Does the body of the request match a known request type and is it valid (by XSD)?
  2. Does the message make sense in this context and can i map it to an operation/handler?
  3. If so, start processing it
  4. Otherwise: error

Upvotes: 2

Related Questions