Build Secure and Paid Rest Web Service in PHP

In earlier post Build Restful Web Services in PHP you have learned how to build Restful Web Service in PHP using Slim Framework.Here you will learn to build professional and secured Restful Web Services.

In some application we need to build paid API which can only be accessed by registered users.For processing each API request we first verify the credentials provided in request is valid then after do further processing.

Here I’m building same earlier example with XML request and response.

Request and Response XML

The following describe how the request will be sent to the server and responses send by server.
Here is example of GetProduct request and response.
http://localhost/SlimAPI/product/GetProduct

<Request>
    <Header>
		<UserName>[Your UserName]</UserName>
		<Password>[Your Password]</Password>
	</Header>	
	<Body>
		<ProductId>1</ProductId>
	</Body>
</Request>
<Response>
	<Header>
		<ServerTime>2013-12-01T14:00:00</ServerTime>
	</Header>
	<Body>
		<Product>
			<ProductId>1</ProductId>
			<ProductTitle>Product A</ProductTitle>
			<Quantity>10</Quantity>
			<Price>10</Price>
		</Product>
	</Body>
</Response>

Database Tables

CREATE TABLE IF NOT EXISTS `products` (
`ID` int(11) NOT NULL,
  `title` varchar(255) NOT NULL,
  `price` double NOT NULL,
  `qty` int(11) NOT NULL
) ENGINE=InnoDB  DEFAULT CHARSET=latin1 AUTO_INCREMENT=2 ;

CREATE TABLE IF NOT EXISTS `users` (
`ID` int(11) NOT NULL,
  `username` varchar(255) NOT NULL,
  `password` varchar(250) NOT NULL,
  `created_date` date NOT NULL,
  `status` tinyint(4) NOT NULL
) ENGINE=InnoDB  DEFAULT CHARSET=latin1 AUTO_INCREMENT=2 ;

CREATE TABLE IF NOT EXISTS `api_requests` (
`ID` int(11) NOT NULL,
  `user_name` varchar(255) NOT NULL,
  `IP` varchar(255) NOT NULL,
  `requested_uri` varchar(255) NOT NULL,
  `created_datetime` timestamp NOT NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP
) ENGINE=InnoDB  DEFAULT CHARSET=latin1 AUTO_INCREMENT=2 ;

Rest Server

Here I’ve added some more functions and functionality to secure and track api requests.
isAuthorizedUser() function checks the credentials of user in each request.
addAPIRequest() function is used to keep each entry of api request and we can build the feature to facilitate limit access to an IP in day.

function isAuthorizedUser($username,$password){
	$sql  = "SELECT * FROM users WHERE username='".$username."' AND password=md5($password) AND status=1";
	$result = mysql_query($sql);
	
	if($result){
		$row    = mysql_fetch_assoc($result);	
		if(!empty($row))		
			return true;
		else
			return false;
	}
}
<?php
require "db.php";
require 'Slim/Slim.php';

\Slim\Slim::registerAutoloader();
$app = new \Slim\Slim();

$app->post('/product/GetProduct/',function () use ($app){
	  $xml = $_POST['xml'];
	  $request  = simplexml_load_string($xml);
	  $username = $request->Header->UserName;
	  $password = $request->Header->Password;
	  $product_id = $request->Body->ProductId;
	  $responseTime = date("Y-m-d H:i:s",time());
	  $responseXML = "<?xml version='1.0'?> 
		             <Response>
					<Header>
						<ServerTime>".$responseTime."</ServerTime>
					</Header>";
	  if(isAuthorizedUser($username,$password)){
		  $sql  = "SELECT * FROM products WHERE ID=".$product_id;
		  $result = mysql_query($sql);
		  $array  = array();
		  while ($row = mysql_fetch_assoc($result)) {
			$product_id = $row['ID'];
			$title 	    = $row['title'];
			$price 	    = $row['price'];
			$qty 		= $row['qty'];
			$responseXML .="<Body>
								<Product>
									<ProductId>".$product_id."</ProductId>
									<ProductTitle>".$title."</ProductTitle>
									<Quantity>".$price."</Quantity>
									<Qty>".$qty."</Qty>
								</Product>
							</Body>";
		  }
	  }else{
		  $responseXML .="<Error>
						   <Code>10002</Code>
						   <message>Product Not found</message>
						 </Error>";
		  
	  }
	 $responseXML .="</Response>";
	 $app->response->headers->set('Content-Type', 'text/xml');
	 addAPIRequest($username,$_SERVER['REMOTE_ADDR'],"/product/GetProduct/");
	 echo $responseXML;
});

function isAuthorizedUser($username,$password){
	$sql  = "SELECT * FROM users WHERE username='".$username."' AND password=md5($password) AND status=1";
	$result = mysql_query($sql);
	
	if($result){
		$row    = mysql_fetch_assoc($result);	
		if(!empty($row))		
			return true;
		else
			return false;
	}
}
function addAPIRequest($user_name,$ip,$requested_uri){
	$sql  = "INSERT into api_requests SET user_name='".$user_name."', ip='$ip',requested_uri='$requested_uri'";
	mysql_query($sql);
}

$app->run();
?>

Rest Client

In client application we are passing user credentials with each request.I am using here php curl to request api call and can be added to database.

<?php
$xml = "<?xml version='1.0'?> 
		<Request>
		<Header>
			<UserName>expertweb</UserName>
			<Password>123</Password>
		</Header>	
		<Body>
			<ProductId>1</ProductId>
		</Body>
	</Request>";
$url = 'http://localhost/SlimAPI/product/GetProduct';
$ch = curl_init();
curl_setopt( $ch, CURLOPT_URL, $url );
curl_setopt( $ch, CURLOPT_POST, true );
curl_setopt( $ch, CURLOPT_RETURNTRANSFER, true );
curl_setopt( $ch, CURLOPT_POSTFIELDS, "xml=".$xml);
$result = curl_exec($ch);
echo $result;
curl_close($ch);
?>

Leave a Reply