How to check if the request is an AJAX request with PHP

PhpAjaxXmlhttprequest

Php Problem Overview


I would like to check server-side if a request to my php page is an ajax request or not.

I saw two ways to do this:

First way: sending a GET parameter in the request which tells the page that this is an AJAX request (=mypage.php?ajax)

mypage.php:

if(isset($_GET['ajax'])) {
    //this is an ajax request, process data here.
}

Second way: set a header to the xmlHttpRequest:

client-side js:

xmlHttpRequestObject.open(“GET”,url,true);
xmlHttpRequestObject.setRequestHeader('X-Requested-With', 'XMLHttpRequest');

mypage.php:

if (!empty($_SERVER['HTTP_X_REQUESTED_WITH']) && strtolower($_SERVER['HTTP_X_REQUESTED_WITH']) == 'xmlhttprequest' ) {
    //request is ajax
}


The fact is, those two ways of doing it can easily be hacked, so it's not secure to check if i get an AJAX request like this.

How can i check if i'm receiving an AJAX request?

Php Solutions


Solution 1 - Php

Here is the tutorial of achieving the result.

Example:

if(!empty($_SERVER['HTTP_X_REQUESTED_WITH']) && strtolower($_SERVER['HTTP_X_REQUESTED_WITH']) == 'xmlhttprequest')
{    
  exit;    
}
continue;

> This checks if the HTTP_X_REQUESTED_WITH parameter is not empty and if it's equal to xmlhttprequest, then it will exit from the script.

Solution 2 - Php

There is no sure-fire way of knowing that a request was made via Ajax. You can never trust data coming from the client. You could use a couple of different methods but they can be easily overcome by spoofing.

Solution 3 - Php

From PHP 7 with null coalescing operator it will be shorter:

$is_ajax = 'xmlhttprequest' == strtolower( $_SERVER['HTTP_X_REQUESTED_WITH'] ?? '' );

Solution 4 - Php

Set a session variable for every page on your site (actual pages not includes or rpcs) that contains the current page name, then in your Ajax call pass a nonce salted with the $_SERVER['SCRIPT_NAME'];

<?php
function create_nonce($optional_salt='')
{
	return hash_hmac('sha256', session_id().$optional_salt, date("YmdG").'someSalt'.$_SERVER['REMOTE_ADDR']);
}
$_SESSION['current_page'] = $_SERVER['SCRIPT_NAME'];
?>

<form>
  <input name="formNonce" id="formNonce" type="hidden" value="<?=create_nonce($_SERVER['SCRIPT_NAME']);?>">
  <label class="form-group">
    Login<br />
    <input name="userName" id="userName" type="text" />
  </label>
  <label class="form-group">
    Password<br />
    <input name="userPassword" id="userPassword" type="password" />
  </label>
  <button type="button" class="btnLogin">Sign in</button>
</form>
<script type="text/javascript">
    $("form.login button").on("click", function() {
        authorize($("#userName").val(),$("#userPassword").val(),$("#formNonce").val());
    });

    function authorize (authUser, authPassword, authNonce) {
        $.ajax({
          type: "POST",
          url: "/inc/rpc.php",
          dataType: "json",
          data: "userID="+authUser+"&password="+authPassword+"&nonce="+authNonce
        })
        .success(function( msg ) {
            //some successful stuff
        });
    }
</script>

Then in the rpc you are calling test the nonce you passed, if it is good then odds are pretty great that your rpc was legitimately called:

<?php
function check_nonce($nonce, $optional_salt='')
{
    $lasthour = date("G")-1<0 ? date('Ymd').'23' : date("YmdG")-1;
    if (hash_hmac('sha256', session_id().$optional_salt, date("YmdG").'someSalt'.$_SERVER['REMOTE_ADDR']) == $nonce || 
        hash_hmac('sha256', session_id().$optional_salt, $lasthour.'someSalt'.$_SERVER['REMOTE_ADDR']) == $nonce)
    {
        return true;
    } else {
        return false;
    }
}

$ret = array();
header('Content-Type: application/json');
if (check_nonce($_POST['nonce'], $_SESSION['current_page']))
{
    $ret['nonce_check'] = 'passed';
} else {
    $ret['nonce_check'] = 'failed';
}
echo json_encode($ret);
exit;
?>

edit: FYI the way I have it set the nonce is only good for an hour and change, so if they have not refreshed the page doing the ajax call in the last hour or 2 the ajax request will fail.

Solution 5 - Php

This function is used from the Yii PHP Framework to check for an AJAX call.

public function isAjax() {
  return isset($_SERVER['HTTP_X_REQUESTED_WITH']) && $_SERVER['HTTP_X_REQUESTED_WITH'] === 'XMLHttpRequest';
}

Solution 6 - Php

$headers = apache_request_headers();
$is_ajax = (isset($headers['X-Requested-With']) && $headers['X-Requested-With'] == 'XMLHttpRequest');

Solution 7 - Php

Try below code snippet

if(!empty($_SERVER['HTTP_X_REQUESTED_WITH']) 
   && strtolower($_SERVER['HTTP_X_REQUESTED_WITH']) == 'xmlhttprequest') 
  {
    /* This is one ajax call */
  }

Solution 8 - Php

You could try using a $_SESSION variable to make sure that a request was made from a browser. Otherwise, you could have the request sent through a database or file [server-side].

Attributions

All content for this solution is sourced from the original question on Stackoverflow.

The content on this page is licensed under the Attribution-ShareAlike 4.0 International (CC BY-SA 4.0) license.

Content TypeOriginal AuthorOriginal Content on Stackoverflow
QuestionBackSlashView Question on Stackoverflow
Solution 1 - PhpVolodymyrView Answer on Stackoverflow
Solution 2 - PhpWayne WhittyView Answer on Stackoverflow
Solution 3 - PhpEmeszenesView Answer on Stackoverflow
Solution 4 - PhpGovCoderView Answer on Stackoverflow
Solution 5 - PhpNanhe KumarView Answer on Stackoverflow
Solution 6 - PhprevokeView Answer on Stackoverflow
Solution 7 - PhpSani KamalView Answer on Stackoverflow
Solution 8 - PhpStatic CastView Answer on Stackoverflow