WSO2Con 2013 CFP Banner

WSF/PHP: Creating Business-Conscious IT Solutions

By Malinda Kaushalye
Date: Tue, 25th Mar, 2008
Level: Intermediate
Reads: 8254 Discuss this article on Stack Overflow

In this article by Malinda Kaushalye Kapuruge, he demonstrates how WSO2 WSF/PHP can be used to implement a typical business solution.

kaushalye's picture
Malinda Kaushalye
Tech-lead
WSO2 Inc.

Applies To

WSO2 WSF/PHP 1.2.0
Environment Linux - Debian, Ubuntu, Fedora

 

Table of Contents

 

Background

As more and more automated B2B communications become loosely-coupled in a distributed environment, the Web services technology is stretching its wings as the perfect solution for these numerous business requirements. Ability to integrate multiple legacy applications as unified systems, that allow communication among clients of heterogeneous platforms at different coordinates of the world is a major challenge faced by software architects everyday.
As a remedy to this situation, WSO2 introduces a series of Web services middle-ware solutions, that can be used for implement business applications. Amongst them is WSO2 Web Services Framework for PHP (WSO2 WSF/PHP), made to the taste of Web services developers and SOA architects within the PHP community.

 

In this Tutorial

This tutorial attempts to describe how to implement a typical business solution using WSO2 WSF/PHP. For this, we will use the scenario given below. We assume the reader has a working knowledge of Apache2 Web server and a basic knowledge of the PHP language.

 

The Scenario

In this scenario, we have a service that accepts purchase orders placed by clients.
Also in the scenario, we have an automated bot as the client that acts on behalf of a particular backpack store. The job of the bot is to ensure that the store maintains its minimum stock levels. If stock goes down beyond a value that's marked as the minimum, the bot automatically places an order on the manufacturer's service.
In order to place a purchase order, the client must send its backpack design to the service. The design is placed in the client's machine as an image. Upon successful receipt of the order, the service will respond to the client, with an acknowledgment. A failure message is sent upon failing to deliver the order.

 

Requirements Identification

In order to implement the above scenario, we need to consider the following areas:

  1. Process of placing a purchase order needs to be automated with less human scrutiny.
  2. Image or the backpack specification need to be sent as an attachment.
  3. Data needs to be sent in a confidential manner that eliminates competitors being able to copy exclusive backpack design.
  4. Request integrity needs to be protected.
  5. Request needs to come from a registered customer and thus requires to be authenticated.
  6. Needs to guarantee non-repudiation on the request. i.e. there should not be any room for the client to later deny the placing of a purchase.

An environment with SOA is best suited for a scenario like this. Web services as a technology is increasingly becoming the choice for such implementations. SOAP in particular comes with adequate features to support such a scenario.

 

WSO2 WSF/PHP as the Solution

WSO2 Web Services Framework for PHP (WSF/PHP) that comes with Apache license v 2.0, is an extension to the Web Services Framework for C (WSF/C) library written in C language for the delopying and consumption of Web services. WSO2 WSF/C framework integrates many Apache Web services projects that are inter-operable with many other Web services implementations including Microsoft's WCF(Windows Communication Foundation). Having Apache Axis2/C as Web services processing engine, the framework provides WS-Security, WS-Reliable Messaging, WS-Addressing, WS-Policy and WS-Security Policy. As an extension to Axis2/C, WSO2 WSF/PHP inherits these very features available in WSO2 WSF/C and presents in a way that is best consumed by the PHP community.
Going back to our scenario, we need to send images as attachments. For this, we will be using the MTOM support available with WSO2 WSF/PHP. Additionally, the message need to confirm to many security requirements and we will be using WS-Security features available in WSO2 WSF/PHP for this.

 

WS-Security Features in WSO2 WSF/PHP

In any context, security requirements need to be carefully assessed. WS-Security and it's family of specifications is an effort to identify and fulfill those for Web services. WSO2 WSF/PHP confirms to the WS-Security specification, and thus, provides greater assurance on the security of messages and specifically on the interoperability with other such implementations. Before jumping into application development, let's analyze security requirements for the scenario given.

Confidentiality is a key requirement in our scenario. If the message is in plain text, any competitor is able to intercept and steal our backpack design. As a solution for this, we can use SOAP message encryption, where the message is encrypted using the service's certificate, and thus, only the manufacturing service can decrypt the message.
Another possibility is a vicious attacker altering our messages. For example, the delivery date or the number of products required can be altered in an attempt to harm the business. Thus message integrity needs to be protected. For that, we can use the SOAP message signing capability.
Apart from integrity, SOAP message signature provides authentication as well. Since you are the single owner of your private key, noone else but you can sign a message. Thus, a service is able to know that the message comes from its trusted client. Authentication can also be fulfilled by adding username tokens in the security header. The token provides a means to carry information of a username and a password. This username/password pair needs to be kept in the service end, to perform validation.
One strong point to using message level security instead of transport layer security (e.g with HTTPS), is that, with message-level security the integrity/confidentiality of the message can be assured even after delivery. Say our request is stored in a temporary location for further processing during which an attack may take place. A mistake so trivial as such, can completely throw you out of business. If the message itself is signed, any alteration to the message is able to be detected, anytime. For example, just before the backpack order is accepted by the manufacturing unit or by the factory supervisor, they can assure that the purchase order is still a valid one, simply by verifying the signature.
Another area that many businesses really worry, is in non-repudiation. In simple terms, it refers to the inability to deny ownership. For example, a client may demand a large stock of backpacks only to later deny placing such an order. With the signature in place, the manufacturer can prove that nobody but the client placed the signature within SOAP body. This is common in our everyday businesses when we sign on our credit card receipts and purchase orders.

 

The Implementation

So far we have analyzed our security requirements for the application and how to fulfill them with the features available in WS-Security. And It's time get our hands a bit dirty.
WSO2 WSF/PHP comes with a very easy to use API, which provides PHP users a very comprehensive way to deploy and consume web services. For this scenario we need to implement a client as well as a service. Please have a look at the WSClient as well as the WSService classes in the WSF/PHP API. These are the main classes that we are going to use to implement our client and the server respectively. For both these implementations we will use the WSF/PHP Security API as well. Let's first have a look at the client implementation.

 

Implementing the Client

Please download and extract the complete source code. Then open the store_client.php file.
The main class we will be using to implement our client is WSClient. We will create a new client object in the following manner.

    $client = new WSClient(array("useWSA" => TRUE,
                                 "useMTOM" => FALSE,
                                 "policy" => $policy,
                                 "securityToken" => $sec_token));

While creating the instance, we will pass certain parameters. In the above line we use WS-Addressing and do not need to send the image as a binary attachment. We would rather send the image as a base64 encoded attachment since we need the image too to be encrypted and signed. Then, we have two more parameters, policy and securityToken, that provides message-level security. In order to provide security, one needs to pass a security token as well as a policy in order to define the required security behavior.

  • WSPolicy : Defines the security behavior. In other words, this defines whether a message needs to be encrypted and/or signed, tokens to be included and algorithms to be used etc.
  • WSSecurityToken : Provides configuration parameters that are required to perform security operations. Such as certificates/keys, passwords etc.

So, we need to provide both these at the point of creating the client. Apart from this, we need to load the image and build the message. For this, we will create an instance of the class WSMessage.

$file = file_get_contents("./design.jpg"); /*Load the file*/
$requestMessage = new WSMessage($requestPayloadString,
        array("to" => "http://localhost:9090/samples/security/store/manuf_service.php",
                "action" => "http://www.back_packers.com/purchaseOrder",
                "attachments" => array("myid1" => $file)));

Here, we provide the address of the service and the SOAP action to be set. As the last parameter we set file content loaded, as an attachment. There we will give an ID(myid1) to the content loaded, and later refer it from the payload or the SOAP body we build.

$requestPayloadString = <<<XML
      <po:Order xmlns:po="http://www.back_packers.com/ws/purchaseorder">
         <po:OrderId>po-98765</po:OrderId>
         <po:Date></po:Date>
         <po:Design>
            <po:FileName>design.jpg</po:FileName>
            <po:Image><xop:Include xmlns:xop="http://www.w3.org/2004/08/xop/include" href="cid:myid1"></xop:Include></po:Image>
         </po:Design>
      </po:Order>
XML;

When everything is in place, all we have to do is to fire the message.

$responseMessage = $client->request($requestMessage);

 

Implementing the Service

Service implementation has a similar approach too. Open the manuf_service.php file. We need to create an instance of WSService class.

$operations = array("purchaseOrder" => "manuf");
$actions = array("http://www.back_packers.com/purchaseOrder" => "purchaseOrder");
$svr = new WSService(array("actions" => $actions,
                           "operations" => $operations,
                           "policy" => $policy,
                           "securityToken" => $sec_token));

Here, we are creating our service with the operation "purchaseOrder". If you open the manuf_service.php file, you will see that there is a php function called "manuf". See how this function is mapped to the operation in the operations array. Once a client invokes the operation named "purchaseOrder", the above function will be executed. In this way, you can define multiple operations mapped to multiple php functions. In our case we will use just one operation. (Note that a server can have multiple services deployed and a service can have multiple operations in it)
Again, we will set an instances of WSPolicy and WSSecurityToken on the server side too, .
While creating the WSSecurityToken, it is required to give a password callback function to return the password for a given user, if user is found. This is somewhat different to the client code, where we set the password directly in the WSSecurityToken instance and require some explanation. Since a service can have multiple clients, it is required to maintain their username/password pairs in the service side. For example, in a database or in any other repository, maintaining these records are highly service/domain specific. For the simplicity in our implementation, we will use an array of username/passowrd pairs. So our password callback function will search the array and return the password for a given username.

// Username Password mapping table
$store_pass_mapping = array(
                    "Raigama" => "RaigamaPW",
                    "Alice" => "abcd!123",
                    "Bob" => "wxyz!123");

function get_store_password_function($username)
{
    global $store_pass_mapping;

    if(isset($store_pass_mapping[$username])){
        $password = $store_pass_mapping[$username];
        return $password;
    }
    else
     return NULL;
}

We have now completed writing the client and the service. In order to complete all bits an pieces left, we place our policy.xml file and certificate/key files. If you plan on running the client in some other location rather than where you extracted the archive, copy the keys folder and policy.xml too.

 

Deploy the Service

Now its time to deploy the service. We assume that you have set WSO2 WSF/PHP with Apache2 server and all your WSF/PHP samples are running properly. If that's the case

  1. copy files to YOUR_APACHE2_DOCUMENT_ROOT/samples/security/store
  2. Start the server
  3. Run the client
    	%sh store_deamon.sh
    	

Store deamon will get started, and you will see stock levels going down.

Stock available = 22 (count down)

Once stock levels reach a predefined minimum level(e.g. 20), the php client executes the placing of an order. If everything goes well, you will see an acknowledgment from the server.

      <manuf:RecievedOrder xmlns:manuf="http://www.factory.com/ws/purchaseOrder">
         <OrderId>po-7</OrderId>
      </manuf:RecievedOrder>

      Deamon is sleeping!

If you have used a tool such as TCPMonitor, you will see that the message is encrypted and signed. Also, there will be a username token and a timestamp added to the SOAP message, something quite similar to this.

 

Conclusion

Web services enable the construction of business applications that collaborates distributed components within and across organizational boundaries. In the above tutorial, we've seen how we can address a typical business situation using the Web services technology. We used WSO2 Web Services Framework for PHP, a very comprehensive framework available to the PHP community.

 

References:

  1. Download the demo
  2. WSO2 WSF/PHP Web Services Extension
  3. WSF/PHP Security API
  4. WS-Security Policy specification
  5. WS-Security Specification

 

Author

Malinda Kaushalye Kapuruge is a Senior Software Engineer, WSO2 Inc. kaushalye at wso2 dot com

AttachmentSize
store_wsf_php_enc_message.xml33.33 KB
WSO2Con 2014