Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Validate an incoming SOAP request to the WSDL in PHP

Tags:

php

soap

wsdl

xsd

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?

like image 795
Glenn Moss Avatar asked Sep 19 '08 23:09

Glenn Moss


1 Answers

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);

}
like image 140
celsowm Avatar answered Sep 30 '22 15:09

celsowm