16

I have a website that needs to increment values in a database based upon user interaction. When users click a button a php script is called that increments the value. I'd like to protect this script from being accessed by outside scripts. Currently a user could write their own web page with a javascript function that hits the same php file repeatedly to blow up the value in the database.

Here's my jquery code that does the incrementing:

jQuery(function(){
$('.votebtn').click(function(e){
    var mynum = $(this).attr('id').substring(0,5);
    $.ajax({
            url:"countvote.php",
            type:"GET",
            data: { 
                thenum:mynum
            },
            cache: false,
            success:function(data) {
                alert('Success!');
                }
            }
        });
});
});

How would I go about making it so that only a call from ajax/jquery on the local server can access 'countvote.php'? If that's not the correct way to go about it, I'm open to any suggestion that will prevent my php script from being abused by outside scripts.

LoneWolfPR
  • 3,978
  • 12
  • 48
  • 84

4 Answers4

41

The solution needs two steps.

Firstly the ajax file must allow access only in ajax request with this code.

define('IS_AJAX', isset($_SERVER['HTTP_X_REQUESTED_WITH']) &&      strtolower($_SERVER['HTTP_X_REQUESTED_WITH']) == 'xmlhttprequest');
if(!IS_AJAX) {die('Restricted access');}

Secondly the ajax file has access in the name of file that call it with command $_SERVER['HTTP_REFERER']. So you can restrict access only in the host server.

$pos = strpos($_SERVER['HTTP_REFERER'],getenv('HTTP_HOST'));
if($pos===false)
  die('Restricted access');

Maybe the code can work only with the second part

user3058968
  • 427
  • 4
  • 2
3

You can check if $_SERVER['HTTP_X_REQUESTED_WITH'] equals xmlhttprequest, but it's not a reliable method to determine whether a request is an AJAX request or not, there is always a way to get around this. But it protects you from random hits like wrongly entered urls, crawlers etc.

cara
  • 1,012
  • 1
  • 9
  • 15
2

Theres not really a 100% method of doing so. AJAX requests are always going to come from a client. Use POST requests instead of GET and that will help deter any issues but not completely stop them and in your php, just drop all get requests.

castis
  • 8,154
  • 4
  • 41
  • 63
  • 2
    Unfortunately this isn't an option. I discovered the hard way that iOS 6 caches POST request results from JQuery/AJAX. So on mobile devices the response info is inaccurate. – LoneWolfPR Mar 15 '13 at 16:13
  • Check this answer to fix that. http://stackoverflow.com/questions/12506897/is-safari-on-ios-6-caching-ajax-results – castis Mar 15 '13 at 16:16
  • 1
    Unless I'm mistaken, I think you need JQuery 1.5 or higher to use the header control. Unfortunately I hamstrung into using 1.3 which doesn't support this. It's part of a CMS that I don't have the ability to update currently. Thanks though. – LoneWolfPR Mar 15 '13 at 16:21
  • Ugh, sucks dude. Sorry I couldn't help. Hope you find your solution! – castis Mar 15 '13 at 16:24
1

I am not sure if this will work, but whats about settings an API key on eg. index.php into a $_SESSION variable, afaik this cannot be visible to the user, unless you do it manually, then in the restricted php file, check the $_SESSION['VOTEAPIKEY'] or whatever

Taki7o7
  • 197
  • 2
  • 11