Php: Soap: Validate namespace of Body children

From FVue
Jump to: navigation, search

Problem

When a SOAP request is in a different namespace then is requested by the WSDL, SoapServer still processes the request. Now that I'm validating the request, if the soap-Body element contains an element in a different namespace, this element will bypass the validation but will nevertheless be processed.

For example, in the SOAP request underneath to a SoapServer with uri `http://mynamespace', the MyAction element will be validated against the generated wsdl/xsd namespace `http://mynamespace/'.

<soap:Envelope xmlns:soap="http://schemas.xmlsoap.org/soap/envelope/" 
                 xmlns="http://mynamespace/">
  <soap:Header/>
  <soap:Body>
    <MyAction/>
  </soap:Body>
</soap:Envelope>

Whereas in the SOAP request underneath, the MyAction element will not be validated because its namespace is `http://othernamespace'. Nevertheless SoapServer *will* process the `MyAction' element.

<soap:Envelope xmlns:soap="http://schemas.xmlsoap.org/soap/envelope/" 
                 xmlns="http://othernamespace/">
  <soap:Header/>
  <soap:Body>
    <MyAction/>
  </soap:Body>
</soap:Envelope>

Environment

  • php-5.5.9
  • zendframework-2.2.10

Solution

Modify the soap-envelope-schema, to allow only elements with specific namespaces within the Body element.

Download the soap-envelope-schema to a local file soap-envelope.xsd and import this file in the local schema validation:

<xsd:import namespace="http://schemas.xmlsoap.org/soap/envelope/" 
             schemaLocation="soap-envelope.xsd"/>

The soap-envelope-schema contains this definition:

  <xs:element name="Body" type="tns:Body" />
  <xs:complexType name="Body" >
    <xs:sequence>
      <xs:any namespace="##any"
               minOccurs="0" 
               maxOccurs="unbounded"
               processContents="lax" />
    </xs:sequence>
    <xs:anyAttribute namespace="##any"
                       processContents="lax" />
  </xs:complexType>

By modifying this definition to not allow *any* namespace but only mynamespace:

  <xs:element name="Body" type="tns:Body" />
  <xs:complexType name="Body" >
    <xs:sequence>
      <xs:any namespace="http://mynamespace"
               minOccurs="0" 
               maxOccurs="unbounded" 
               processContents="lax" />
    </xs:sequence>
    <xs:anyAttribute namespace="http://mynamespace" 
                       processContents="lax" />
  </xs:complexType>

the Body element may only contain elements with the namespace http://mynamespace.

Script to transform soap-envelope.xsd

With an XSLT stylesheet soap-envelope.xslt you can leave the original XML Schema (soap-envelope.orig.xsd) intact and insert your own namespace using this command:

 xsltproc --stringparam namespace 'http://mynamespace/' \
     soap-envelope.xslt soap-envelope.orig.xsd > soap-envelope.xsd

The soap-envelope.xslt:

<?xml version="1.0"?>
<xsl:stylesheet version="1.0" 
    xmlns:xs="http://www.w3.org/2001/XMLSchema"
    xmlns:wsdl="http://schemas.xmlsoap.org/wsdl/"
    xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
    xmlns:soap="http://schemas.xmlsoap.org/wsdl/soap/">
 
<xsl:param name="namespace"></xsl:param>
 
<xsl:output method="xml" indent="yes"/>
<xsl:strip-space elements="*"/>
 
<xsl:template match="node()|@*">
  <xsl:copy>
    <xsl:apply-templates select="node()|@*"/>
  </xsl:copy>
</xsl:template>
 
<xsl:template match="xs:complexType[@name = 'Body']/xs:sequence/xs:any">
    <xsl:element name="xs:any">
        <xsl:attribute name="namespace"><xsl:value-of select="$namespace"/></xsl:attribute>
        <xsl:attribute name="minOccurs">0</xsl:attribute>
        <xsl:attribute name="maxOccurs">unbounded</xsl:attribute>
        <xsl:attribute name="processContents">lax</xsl:attribute>
    </xsl:element>
</xsl:template>
 
<xsl:template match="xs:complexType[@name = 'Body']/xs:anyAttribute">
    <xsl:element name="xs:anyAttribute">
        <xsl:attribute name="namespace"><xsl:value-of select="$namespace"/></xsl:attribute>
        <xsl:attribute name="processContents">lax</xsl:attribute>
    </xsl:element>
</xsl:template>
 
</xsl:stylesheet>

Keywords

SoapServer, SoapClient, Zend\Soap\Server

Comments

blog comments powered by Disqus