SOA: Implementing Message-Level Security

Exclusive offer: get 100% off this eBook here
SOA and WS-BPEL

SOA and WS-BPEL — Save 100%

Compose Service-Oriented Architecture Solutions with PHP and Open-Source ActiveBPEL with this book and eBook

₨924.00    ₨0.00
by Yuli Vasiliev | April 2010 | .NET BPEL Microsoft SOA Web Services

This article by Yuli Vasiliev, author of the book SOA and WS-BPEL, provides an example of how message-level security can be implemented in a Web services application.

One simple way to secure the PO Web service would be to provide legitimate users with a token. This approach assumes that each SOAP message containing a PO document sent by a consumer will contain a username/password pair, which is checked against the database when it arrives at the service provider.

While this approach allows the service provider to obtain the information about the consumer to make an authorization decision, a significant disadvantage is that the credentials passed within the message are actually independent of the message payload, and thus, once obtained by a malicious user, may be used to consume the service on behalf of a legitimate user. Of course, you can still use SSL to ensure transport-level security. Often, though, a SOAP message sent from a service consumer to a service provider is processed by an intermediate service or services, running the risk of a malicious user stealing the password travelling with the message.

This section discusses how you might work around the above issue by using a hash generated from the value of a particular element or elements of the PO document being transmitted with the message, rather than sending a fixed token. On the client, you might include that hash as part of the SOAP message payload also containing the PO document as the other part. The server in turn is responsible for retrieving the hashed token from the message and checking whether this hash corresponds to the PO that arrived in the same message. Depending on the algorithm used to generate a hash, each new PO document may come with a potentially different hashed token, which makes it harder for a malicious user to illegally access the service.

It is important to realize that the above security mechanism does not ensure a private way to transfer the data, since the payload of a SOAP message being transmitted is not encrypted. As for data integrity, you may be fully confident that the message has not been modified in transit only if the hash transmitted within the message was generated upon the entire payload rather than some parts of it. What does this security mechanism do then? Well, it prevents unauthorized users from consuming the service. That is it.

Diagrammatically, the security mechanism discussed here might look like the following figure:

SOA: Implementing Message-Level Security

Here is the PHP code you might use to generate the sha1 hash upon the value of the pono element of a PO XML document:

$xmlpo = simplexml_load_string($po);
$pono = $xmlpo->purchaseOrder->pono;
$hash=sha1($pono);

While the previous figure illustrates an example assuming that the hash is generated upon the value of the pono element only, in reality, however, the hash might be built upon any other PO document's element or, even better, upon a combination of elements. The more elements are involved and the more complicated the hashing algorithm is, the harder it will be for a malicious user to guess that algorithm. When choosing elements for hashing, it is always a good idea to consider the element whose value uniquely identifies the document, since it will be most likely used as the primary key when storing the document in the database. So utilizing the pono in this particular example is essential, since an attempt to submit a new PO document with the same pono will fail due to the primary key constraints placed upon the database table holding incoming PO documents.

As you can see, with the above approach, you don't even need to create and hold the security accounts in the database, since the security measures are incorporated in a SOAP message itself, thus enabling message-level security.

As an alternative to including credentials in the SOAP message body, you might include them in the SOAP message headers. To achieve this with the PHP SOAP extension, you might use the following predefined classes: SoapHeader and SoapVar. Using SOAP message headers to send secure messages, as well as implementing WS-Security authentication, is discussed in detail later, in the Using SOAP Message Headers and Using WS-Security for Message-Level Security sections.

In the remainder of this section, you will learn how to implement a secure version of the PO Web service, based on the approach outlined above.

The first step is to create the WSDL document for the updated PO Web service. For that, you might create the following document and save it as po_secure.wsdl in the WebServices\wsdl directory:

<?xml version="1.0" encoding="utf-8"?>
<definitions name ="poServiceSecure"
xmlns:http="http://schemas.xmlsoap.org/wsdl/http/"
xmlns:soap="http://schemas.xmlsoap.org/wsdl/soap/"
xmlns:xsd="http://www.w3.org/2001/XMLSchema"
xmlns="http://schemas.xmlsoap.org/wsdl/"
targetNamespace="http://localhost/WebServices/wsdl/po_
secure.wsdl">
<message name="getPlaceOrderInput">
<part name="hash" element="xsd:string"/>
<part name="po" element="xsd:string"/>

</message>
<message name="getPlaceOrderOutput">
<part name="body" element="xsd:string"/>
</message>
<portType name="poServiceSecurePortType">
<operation name="placeOrder">
<input message="tns:getPlaceOrderInput"/>
<output message="tns:getPlaceOrderOutput"/>
</operation>
</portType>
<binding name="poServiceSecureBinding"
type="tns:poServiceSecurePortType">
<soap:binding style="rpc"
transport="http://schemas.xmlsoap.org/soap/http"/>
<operation name="placeOrder">
<soap:operation
soapAction="http://localhost/WebServices/ch4/placeOrder"/>
<input>
<soap:body use="literal"/>
</input>
<output>
<soap:body use="literal"/>
</output>
</operation>
</binding>
<service name="poServiceSecure">
<port name="poServiceSecurePort"
binding="tns:poServiceSecureBinding">
<soap:address
location="http://localhost/WebServices/ch4/SoapServer_secure.php"/>
</port>
</service>
</definitions>

As you can see, this WSDL assumes two message parts in the input message of the placeOrder operation defined here. So, make sure that the binding style defined in the document is rpc.

Next, you might want to create the PHP handler class representing the underlying logic of the service discussed here. For that, you might create the following purchaseOrder.php script in the WebServices\ch4 directory:

<?php
//File purchaseOrder_secure.php
class purchaseOrder {
public function placeOrder($hash, $po) {
if(!$conn = oci_connect('xmlusr', 'xmlusr', '//localhost/XE')){
throw new SoapFault("Server","Failed to connect to database");
};
$xmlpo = simplexml_load_string($po);
$pono = $xmlpo->pono;
$pswd=sha1($pono);
$this->checkOrder($hash, $pswd);
$sql = "INSERT INTO purchaseOrders VALUES(:po)";
$query = oci_parse($conn, $sql);
oci_bind_by_name($query, ':po', $po);
if (!oci_execute($query)) {
throw new SoapFault("Server","Failed to insert PO");
};
$msg='<rsltMsg>PO inserted!</rsltMsg>';
return $msg;
}
private function checkOrder($hash, $pswd) {
if ($pswd!=$hash) {
throw new SoapFault("Server","You're not authorized to
consume this service");
}
}
}
?>

In this purchaseOrder class, in the first highlighted code block you load the PO XML document as a SimpleXMLElement object and then extract the value of the pono element. Next, you generate the sha1 hash upon the extracted pono and call the checkOrder private method of purchaseOrder. The code for this method is also highlighted in the listing and is used to check to see whether the hash generated here is equal to the hash that arrived with the message. If there is a mismatch, a SoapFault exception is thrown.

The implementation of the SOAP server script to be used in this example is straightforward. It is assumed that you save the following SOAP server script as SoapServer_secure.php in the WebServices/ch4 directory:

<?php
//File: SoapServer_secure.php
require_once "purchaseOrder_secure.php";
$wsdl= "http://localhost/WebServices/wsdl/po_secure.wsdl";
$srv= new SoapServer($wsdl);
$srv->setClass("purchaseOrder");
$srv->handle();
?>

Now that you have the service created, all that's left is to build a client script to test the newly created service. For that, you might create the SoapClient_secure.php client script shown below:

<?php
//File: SoapClient_secure.php
$wsdl = "http://localhost/WebServices/wsdl/po_secure.wsdl";
$xmldoc = simplexml_load_file('purchaseOrder.xml');
$pono = $xmldoc->pono;
$hash=sha1($pono);
$podoc=$xmldoc->asXML();
$client = new SoapClient($wsdl);
try {
print $result=$client->placeOrder($hash, $podoc);
}
catch (SoapFault $exp) {
print $exp->getMessage();
}
?>

Before you can execute this SOAP client script, you need to have a purchaseOrder.xml document containing a PO XML document. So, make sure to copy the purchaseOrder.xml document from the WebServices\ch2 to WebServices\ch4 directory.

In this client script, you extract the value of the pono element from the PO loaded as a SimpleXMLObject from purchaseOrder.xml, and then generate an sha1 hash upon the extracted value. The generated hash and the PO document converted into a string are then passed to the placeOrder SOAP function as arguments.

Unlike the above client, the following one uses a more complicated algorithm for generating the hash. In particular, it generates an sha1 hash upon the pono and shipName concatenated together.

<?php
//File: __SoapClient_secure.php
$wsdl = "http://localhost/WebServices/wsdl/po_secure.wsdl";
$xmldoc = simplexml_load_file('purchaseOrder.xml');
$pono = $xmldoc->pono;
$shipName = $xmldoc->shipTo->name;
$mix=$pono.$shipName;
$hash=sha1($mix);
$podoc=$xmldoc->asXML();
$client = new SoapClient($wsdl);
try {
print $result=$client->placeOrder($hash, $podoc);
}
catch (SoapFault $exp) {
print $exp->getMessage();
}
?>

Now if you try to run the __SoapClient_secure.php script shown above, you should get the following error message:

You're not authorized to consume this service

This is because you haven't changed the authentication algorithm on the server side yet. To handle this task, you might modify the purchaseOrder_secure.php script as shown overleaf (the script has been cut down to save space):

For the full version, see the __purchaseOrder_secure.php script in the WebServices\ch4 directory of the downloadable ZIP archive accompanying this article. However, before you put the script into action, make sure to rename it to purchaseOrder_secure.php.

<?php
//File __purchaseOrder_secure.php
class purchaseOrder {
public function placeOrder($hash, $po) {
...
$xmlpo = simplexml_load_string($po);
$pono = $xmlpo->pono;
$shipName = $xmlpo->shipTo->name;
$mix=$pono.$shipName;
$pswd=sha1($mix);
$this->checkOrder($hash, $pswd);
...
}
...
}
?>

Now the mechanism of generating the hash on the client agrees with the one used on the server. So, if you now run the __SoapClient_secure.php script, you should not have a problem.

SOA and WS-BPEL Compose Service-Oriented Architecture Solutions with PHP and Open-Source ActiveBPEL with this book and eBook
Published: September 2007
eBook Price: ₨924.00
Book Price: ₨350.00
See more
Select your format and quantity:

Using SOAP Message Headers

In the preceding section you saw an example of how you might implement message-level security by including a hash generated upon the data from the document being transmitted into the message. The mechanism discussed there assumed that you pass the hash generated as part of the message payload, which means you had to define another part of the input message in the WSDL document in order to carry the hash. However, sending the hash as part of the payload is probably not a good idea, because the hash, acting as a security measure in this case, can be considered metadata rather than user data transmitted within the SOAP message payload.

The following figure gives a graphical depiction of the process that takes place on the server side when a secure message arrives.

SOA: Implementing Message-Level Security

Here is the explanation of the steps in the figure:

  • Step 1: The service provider receives the message containing a PO document as the payload and the hash as a header.
  • Step 2: The overridden handle method of an extended SOAP server class checks whether the hash that arrived with the message as a header is equal to the hash generated upon the pono element of the PO document composing the message payload.
  • Step 3: If the check performed in Step 2 returns true, the SOAP server passes the PO document to an instance of the PHP handler class for further processing.
  • Step 4: Otherwise, the server stops processing the message, throwing a SOAP exception.

An important point about the security mechanism discussed here is that the SOAP server processes the hash passed in as a header of the message before the message payload is sent to the handler class for processing. So, if the hash passed in is not equal to the hash generated upon the value of the pono element of the PO document that arrived as the payload, then the server generates a SOAP fault exception and stops processing the message.

The rest of this section discusses how to implement a service acting as outlined in the above scenario.

As usual, let's start with creating the WSDL document for the updated poServiceSecure. For that, create the po_headers.wsdl document in the WebServices\ch4 directory, which might look as follows:

<?xml version="1.0" encoding="utf-8"?>
<definitions name ="poServiceSecure"
xmlns:http="http://schemas.xmlsoap.org/wsdl/http/"
xmlns:soap="http://schemas.xmlsoap.org/wsdl/soap/"
xmlns:xsd="http://www.w3.org/2001/XMLSchema"
xmlns="http://schemas.xmlsoap.org/wsdl/"
targetNamespace=
"http://localhost/WebServices/wsdl/po_headers.wsdl">
<message name="getPlaceOrderInput">
<part name="po" element="xsd:string"/>
</message>
<message name="getPlaceOrderOutput">
<part name="body" element="xsd:string"/>
</message>
<portType name="poServiceSecurePortType">
<operation name="placeOrder">
<input message="tns:getPlaceOrderInput"/>
<output message="tns:getPlaceOrderOutput"/>
</operation>
</portType>
<binding name="poServiceSecureBinding"
type="tns:poServiceSecurePortType">
<soap:binding style="document"
transport="http://schemas.xmlsoap.org/soap/http"/>
<operation name="placeOrder">
<soap:operation
soapAction="http://localhost/WebServices/ch4/placeOrder"/>
<input>
<soap:body use="literal"/>
</input>
<output>
<soap:body use="literal"/>
</output>
</operation>
</binding>
<service name="poServiceSecure">
<port name="poServiceSecurePort"
binding="tns:poServiceSecureBinding">
<soap:address
location="http://localhost/WebServices/ch4/SoapServer_headers.php"/>
</port>
</service>
</definitions>

There are a couple of points worth noting about the WSDL document shown opposite. First, the input message of the placeOrder operation defined here consists of one part only—you don't need to define the hash part any more, since you're not going to transmit a hash as part of the message payload. Second, you may use the binding style document, since the input message payload is going to contain only a PO document.

<?php
//File purchaseOrder_headers.php
class purchaseOrder {
public function placeOrder($po) {
if(!$conn = oci_connect('xmlusr', 'xmlusr', '//localhost/XE')){
throw new SoapFault("Server","Failed to connect to database");
};
$sql = "INSERT INTO purchaseOrders VALUES(:po)";
$query = oci_parse($conn, $sql);
oci_bind_by_name($query, ':po', $po);
if (!oci_execute($query)) {
throw new SoapFault("Server","Failed to insert PO");
};
$msg='<rsltMsg>PO inserted!</rsltMsg>';
return $msg;
}
}
?>

The secSoapServer class is shown in the following snippet that extends the SoapServer predefined SOAP extension class, overriding the parent's handle method. It is assumed that you save this class as secSoapServer.php in the WebServices\ch4 directory.

<?php
//File: secSoapServer.php
class secSoapServer extends SoapServer {
function handle($req) {
$env = simplexml_load_string($req);
$hash= $env->xpath('//ns1:hash');
$hash = (string) $hash[0];
$po= $env->xpath('//po');
$po = simplexml_load_string((string)$po[0]);
$pono = $po->xpath('//pono');
$pono = (string)$pono[0];
$pswd=sha1($pono);
if ($pswd!=$hash) {
throw new SoapFault("Server","You're not authorized to
consume this service");
};
parent::handle();
}
}
?>

In the overridden handle method, you first convert the value of the argument passed in to the method and representing the request message received by the server into a SimpleXMLElement object, which makes it possible for you to access the request message as XML. In particular, you use the xpath SimpleXMLElement method to access the hash encapsulated within the message header block. Using the same method, you obtain the message payload, specifying //po as the path argument for the xpath method. If you recall from the po_headers.wsdl document discussed earlier in this section, po is the name of the input message part that represents the message payload. Next, you load the obtained payload as another SimpleXMLElement object that you then use to access the pono element in the PO document representing the payload. It's explained later in this section why you have to create another SimpleXMLElement object to access the payload, rather than accessing it via the SimpleXMLElement object created earlier and representing the entire message. Finally, to make use of the parent handle method functionality, you explicitly call this method.

Now that you have the secSoapServer class created, you can put it into action with the following SOAP server script, which you should save as SoapServer_headers. php in the WebServices/ch4 directory:

<?php
//File: SoapServer_headers.php
require_once "purchaseOrder_headers.php";
require_once "secSoapServer.php";
$wsdl= "http://localhost/WebServices/wsdl/po_headers.wsdl";
$srv= new secSoapServer($wsdl);
$srv->setClass("purchaseOrder");
$srv->handle($HTTP_RAW_POST_DATA);
?>

To test the newly created service, you might create and then execute the following client script:

<?php
//File: SoapClient_headers.php
$wsdl = "http://localhost/WebServices/wsdl/po_headers.wsdl";
$xmldoc = simplexml_load_file('purchaseOrder.xml');
$pono = $xmldoc->pono;
$hash=sha1($pono);
$header = new SOAPHeader('http://localhost/WebServices/ch4/headers',
'hash', $hash);
$client = new SoapClient($wsdl);
$client->__setSOAPHeaders($header);
$podoc=$xmldoc->asXML();
try {
print $result=$client->placeOrder($podoc);
}
catch (SoapFault $exp) {
print $exp->getMessage();
}
?>

As you no doubt have guessed, the highlighted code in the above script is used to set up the header block in the request message being sent to the server. In this particular example, the header block transports the hash used as a security measure.

Now let's turn back to the secSoapServer class, discussed a bit earlier in this section. Examining the handle method overridden in this class, you may wonder why you would want to use another SimpleXMLElement object to access the payload, despite the fact that you already have a SimpleXMLElement object representing the entire message. To understand why you have to do it this way, it would be a good idea to look at the request message passed to the handle method for processing.

There are several ways in which you can do this. For example, you might make use of the __getLastRequest method of a SoapClient on the client side. As a result, you should get the following message:

<SOAP-ENV:Envelope ...>
<SOAP-ENV:Header>
<ns1:hash>da30b3a3056d477be870db86a140a4a36cf7b243</ns1:hash>
</SOAP-ENV:Header>
<SOAP-ENV:Body>
<po>
&lt;?xml version="1.0"?&gt;
&lt;purchaseOrder&gt;
&lt;pono&gt;108128476&lt;/pono&gt;
&lt;billTo&gt;
...
&lt;/purchaseOrder&gt;
</po>
</SOAP-ENV:Body>
</SOAP-ENV:Envelope>

So, to extract the hash from the above message you use the following code in the handle method:

$env = simplexml_load_string($pack);
$hash= $env->xpath('//ns1:hash');
$hash = (string) $hash[0];

However, since the PO document composing the message payload contains HTML entities, obtaining the value of the pono element of the PO is a bit tricky. First, you obtain the string representing the PO and containing HTML entities. Next, you load this string as a SimpleXMLElement object and then get the pono element with the xpath method as follows:

$po= $env->xpath('//po');
$po = simplexml_load_string((string)$po[0]);
$pono = $po->xpath('//pono');
$pono = (string)$pono[0];

This is not the case, though, if the message payload is defined as XML rather than a string. For example, you might use the following WSDL document to describe the poServiceSecure service discussed here:

<definitions name ="poServiceSecure"
xmlns:http="http://schemas.xmlsoap.org/wsdl/http/"
xmlns:soap="http://schemas.xmlsoap.org/wsdl/soap/"
xmlns:xsd="http://www.w3.org/2001/XMLSchema"
targetNamespace=
"http://localhost/WebServices/wsdl/po_headers.wsdl"
xmlns:xsd1="http://localhost/WebServices/schema/po/"
xmlns="http://schemas.xmlsoap.org/wsdl/">
<import namespace="http://localhost/WebServices/schema/po/"
location="http://localhost/WebServices/schema/po.xsd"
/>
<message name="getPlaceOrderInput">
<part name="po" element="xsd1:purchaseOrder"/>
</message>
...
</definitions>

In this case, the request message issued by a consumer of poServiceSecure would look as follows:

<SOAP-ENV:Envelope ...>
<SOAP-ENV:Header>
<ns1:hash>da30b3a3056d477be870db86a140a4a36cf7b243</ns1:hash>
</SOAP-ENV:Header>
<SOAP-ENV:Body>
<SOAP-ENV:placeOrder>
<po>
<pono>108128476</pono>
<shipTo>
...
</po>
</SOAP-ENV:placeOrder>
</SOAP-ENV:Body>
</SOAP-ENV:Envelope>

This simplifies things at the server end. Now, the code extracting the hash and the value of the pono element in the overridden handle method of secSoapServer might look as follows:

$env = simplexml_load_string($pack);
$hash= $env->xpath('//ns1:hash');
$hash = (string) $hash[0];
$pono= $env->xpath('//pono');
$pono = (string)$pono[0];

In the above example, you use only one SimpleXMLElement object, loading the entire request message into it and then extracting first the hash and then the value of the pono element of the PO document composing the message payload.

Using WS-Security for Message-Level Security

W hile the security approach discussed in the preceding section may be efficient in many PHP SOAP extension-based solutions and is easy to maintain, it does not represent a standard security mechanism.

If you want to employ a standard SOAP security mechanism, consider WS-Security, a core security specification describing a mechanism for implementing message-level security, providing the means of encapsulating security measures in SOAP messages.

For more information on WS-Security, you can visit the OASIS Web Services Security (WS-Security) page containing links to specification documents. This page can be found at: http://www.oasis-open. org/committees/tc_home.php?wg_abbrev=wss.

Actually, the PHP SOAP extension provides no support for WS-Security. To take advantage of the technology, you have to explicitly create the required WS-Security headers and put them into the SOAP message. The header of the message in this case should look as follows:

<SOAP-ENV:Header>
<ns1:Security
xmlns:ns1="http://schemas.xmlsoap.org/ws/2003/06/secext">
<ns1:UsernameToken>
<ns1:Username>yourusername</ns1:Username>
<ns1:Password>yourpassword</ns1:Password>
</ns1:UsernameToken>
</ns1:Security>
</SOAP-ENV:Header>

It is interesting to note that WS-Security is not the only WS-* specification that utilizes message headers—virtually all WS-* specifications do that. For example, WS-Addressing transports message exchange information with SOAP headers.

Now that you know what a WS-Security header looks like, let's create a client script that would be able to post messages containing such a header.

To start with, you need to create two classes that will be used in the process of creating a WS-Security header. The first class should look as follows:

<?php
//File: UsernameToken.php
class UsernameToken {
private $Username;
private $Password;
public function __construct($Username, $Password) {
$this->Username = $Username;
$this->Password = $Password;
}
}
?>

When creating an instance of this class you will have to specify the username and password to be encapsulated in the WS-Security header being created.

The second class should look as follows:

<?php
//File: varUsernameToken.php
class varUsernameToken {
private $UsernameToken;
public function __construct($UsernameToken) {
$this->UsernameToken = $UsernameToken;
}
}
?>

This class will be used to create a SoapVar variable from an instance of the UsernameToken class discussed previously.

Assuming that you have saved the above classes in the UsernameToken.php and varUsernameToken.php scripts respectively, you can now create the following client script:

<?php
//File: SoapClient_wssecurity.php
require_once 'UsernameToken.php';
require_once 'varUsernameToken.php';
//setting up the variables
$ns1 = 'http://schemas.xmlsoap.org/ws/2003/06/secext';
$wsdl = "http://localhost/WebServices/wsdl/po_headers.wsdl";
//generating the hash
$xmldoc = simplexml_load_file('purchaseOrder.xml');
$pono = $xmldoc->pono;
$hash=sha1($pono);
//building WS-Security tags
$usr = new SoapVar('usr', XSD_STRING,null,null,null,$ns1);
$pswd = new SoapVar('pswd', XSD_STRING,null,null,null,$ns1);
$tok = new UsernameToken($usr, $pswd);
$token = new SoapVar($tok, SOAP_ENC_OBJECT,null,null,'UsernameToken'
,$ns1);
$varToken = new varUsernameToken($token);
$token = new SoapVar($varToken, SOAP_ENC_OBJECT,null,null,'UsernameT
oken',$ns1);
$header = new SOAPHeader($ns1, 'Security', $token);
//creating the client
$client = new SoapClient($wsdl, array('trace' => 1));
$client->__setSOAPHeaders($header);
$podoc=$xmldoc->asXML();
try {
print $result=$client->placeOrder($podoc);
}
catch (SoapFault $exp) {
print $exp->getMessage();
}
print "REQUEST:\n".$client->__getLastRequest()."\n";
?>

As you might guess, the highlighted block of code is responsible for setting up a WS-Security header to be sent with the request message. You define a SoapVar object upon an instance of the UsernameToken class defined earlier, and then use this SoapVar object when defining an instance of the varUsernameToken class. The latter in turn is used when defining another SoapVar object, which is then passed to the SoapHeader constructor.

For simplicity, this client script uses the same WSDL document as in the preceding example. This means that when you execute the above client, the SoapServer_headers.php server script discussed in the preceding section will be invoked. So, the authentication will fail, because the secSoapServer class utilized within SoapServer_headers.php is not supposed to work with a WS-Security header. In a real-world scenario, though, it is assumed that the receiver understands WS-Security.

However, the purpose of the client script discussed here is to show how you can set up a WS-Security header rather than how you can handle it on the server side. To achieve this goal, you create a SoapClient in debugging mode, and then use the __getLastRequest method to print out the request message. In this case, the request message will be printed regardless of whether the server fails to process the message or not.

To complete this example, though, you might create the SOAP server that will understand WS-Security headers. For that, you might want to create a class that extends the SoapServer class, similar to secSoapServer used in the preceding example, in order to handle WS-Security headers on the server side.

All that's left is to run the script to check to see what the request message being generated looks like. When examining the request message, you should notice that it contains the header block shown at the beginning of this section.

Summary

In this article, we learnt how to secure services built with PHP SOAP extension.

If you have read this article you may be interested to view :

SOA and WS-BPEL Compose Service-Oriented Architecture Solutions with PHP and Open-Source ActiveBPEL with this book and eBook
Published: September 2007
eBook Price: ₨924.00
Book Price: ₨350.00
See more
Select your format and quantity:

About the Author :


Yuli Vasiliev

Yuli Vasiliev is a software developer, freelance author, and consultant currently specializing in open-source development, Oracle technologies, and service-oriented architecture (SOA). He has over 10 years of software development experience as well as several years of technical writing experience. He wrote a series of technical articles for Oracle Technology Network (OTN) and Oracle Magazine.

Contact Yuli Vasiliev

Books From Packt

Oracle SOA Suite Developer's Guide
Oracle SOA Suite Developer's Guide

Service Oriented Architecture with Java
Service Oriented Architecture with Java

Business Process Driven SOA using BPMN and BPEL
Business Process Driven SOA using BPMN and BPEL

Building SOA-Based Composite Applications Using NetBeans IDE 6
Building SOA-Based Composite Applications Using NetBeans IDE 6

ASP.NET MVC 1.0 Quickly
ASP.NET MVC 1.0 Quickly

.NET Compact Framework 3.5 Data Driven   Applications
.NET Compact Framework 3.5 Data Driven Applications

Oracle Web Services Manager
Oracle Web Services Manager

Microsoft Silverlight 4 Data and Services Cookbook
Microsoft Silverlight 4 Data and Services Cookbook

Code Download and Errata
Packt Anytime, Anywhere
Register Books
Print Upgrades
eBook Downloads
Video Support
Contact Us
Awards Voting Nominations Previous Winners
Judges Open Source CMS Hall Of Fame CMS Most Promising Open Source Project Open Source E-Commerce Applications Open Source JavaScript Library Open Source Graphics Software
Resources
Open Source CMS Hall Of Fame CMS Most Promising Open Source Project Open Source E-Commerce Applications Open Source JavaScript Library Open Source Graphics Software