Hi - I have in my website a PHP page which retrieves data from my database to be presented in my website. This page is called via AJAX. How can I restrict the access to it only from pages within my website so users who wants to abuse it and get this data not from the website (e.g. posting HTTP request from their server) itself won't be able to do so ?
views:
92answers:
5There are a variety of options depending on what your underlying need is, whether its a service you will be letting others access, vs something internal only. Here is an article with some good in-depth explanation of the options.
http://java.sun.com/developer/technicalArticles/J2EE/usingapikeys/
This can not really be done if stated as above, you would need to redesign and implement some kind of authentication scheme, but even that can be emulated. The short answer is that if a web browser can access it then anything can access it as long as it pretends to be a browser.
There are things you could do to make it harder for someone, like verifying HTTP header fields such as Referer and User-Agent, and implementing session verification in the AJAX calls.
Alas, that's not possible. Anything Javascript can do, an 'abuser' can also do from his server. You can make it more difficult by obfuscating the javascript and protocol, making it harder to sniff. There are various free and non-free javascript obfuscators (also knows as "minimization") available. Obfuscating the protocol you can do by implementing a simple encryption scheme (making it more advanced won't help, as the key must always be embedded in your code anyway) for the data sent and received.
JavaScript running on another site will be unable to access your site because of the Same-Origin Policy for XHR. But nothing is stopping someone from building a PHP+CURL script to "proxy" the data from your ajax backed to make it appear as though it was running on their server. Trying to blacklist clients is messy, ip address are cheap and free http proxies are plentiful.
In short there is nothing special about your javascript. A client can do whatever he wants, and you can't force him to behave, this is the basis of "client site trust". A hacker can use something like tamperdata or even firebug to identify HTTP requests and he will be able to replay them or forge them with CURL.
You could try obfuscating your javascript. But at the end of the day an attacker is just going to replay the http request, and there is absolutely thing you can do about it.
This is what I do,
- On your website, create a secret string. I use the HMAC($_SERVER['REMOTE_ADDR'], key).
- Write the secret in a Javascript var.
- On the AJAX call, pass this string as a parameter.
- On the AJAX server, do the hash again. If it's matches the parameter, the call is from your page.
EDIT: Code examples,
In your website, you do this,
$key = 'supersecretkey'; // This is your security, don't expose this
$nonce = rand();
$timestamp = time();
$signature = hash_hmac('sha1', $_SERVER['REMOTE_ADDR'] . $nonce . $timestamp, $key);
Print out the vars to the page,
<script type="text/javascript">
<?php
echo " var signature = '" . $signature . "';\n";
echo " var nonce = '" . $nonce . "';\n";
echo " var timestamp = '" . $timestamp . "';\n";
?>
</script>
When you make AJAX call, pass the 3 parameters to the server,
http://example.com?signature=...&nonce=...&timestamp=...
On the AJAX server, do the calculation again,
$key = 'supersecretkey'; // This is your security, don't expose this
$nonce = $_REQUEST['nonce'];
$timestamp = $_REQUEST['timestamp'];
$signature = hash_hmac('sha1', $_SERVER['REMOTE_ADDR'] . $nonce . $timestamp, $key);
if ($signature == $_REQUEST['signature'])
// the call if from my page.
You can also chech timestamp for currency and nonce for replay (need session or data store).