Как проверить, является ли запрос AJAX-запросом с помощью PHP


Я хотел бы проверить на стороне сервера, является ли запрос на мою страницу php запросом ajax или нет.

Я видел два способа сделать это:

Первый способ: отправка параметра GET в запросе, который сообщает странице, что это запрос AJAX (=mypage.php?ajax)

Mypage.php :

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

Второй способ: установите заголовок в xmlHttpRequest:

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
}

Дело в том, что эти два способа сделать это можно легко взломать, так что это не безопасно проверить, получу ли я запрос AJAX, подобный этому.

Как я могу проверить, получаю ли я запрос AJAX?

Author: Tshepang, 2013-08-15

7 answers

Нет надежного способа узнать, что запрос был сделан через Ajax. Вы никогда не сможете доверять данным, поступающим от клиента. Вы могли бы использовать несколько различных методов, но их можно легко преодолеть с помощью подмены.

 22
Author: Wayne Whitty, 2013-08-15 19:49:43

Вот учебное пособие по достижению результата.

Пример:

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

Это проверяет, не является ли параметр HTTP_X_REQUESTED_WITH пустым, и если он равен xmlhttprequest, то он выйдет из скрипта.

 38
Author: Volodymyr, 2018-02-13 04:09:32

Установите переменную сеанса для каждой страницы на вашем сайте (фактические страницы не включают или rpc), которая содержит текущее имя страницы, затем в вызове ajax передайте значение, не содержащее $_SERVER['ИМЯ_СКРИПТА']:

<?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>

Затем в rpc, который вы вызываете, проверьте пройденный вами nonce, если он хорош, то вероятность того, что ваш rpc был законно вызван, довольно велика:

<?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;
?>

Редактировать: К вашему сведению, то, как я установил, nonce работает только в течение часа и меняется, поэтому, если они не обновились страница, выполняющая вызов ajax в течение последнего часа или 2, выполнит запрос ajax с ошибкой.

 7
Author: user3002997, 2013-11-18 03:51:39
$headers = apache_request_headers();
$is_ajax = (isset($headers['X-Requested-With']) && $headers['X-Requested-With'] == 'XMLHttpRequest');
 4
Author: revoke, 2014-06-25 13:32:48

Эта функция используется в фреймворке yii для проверки вызовов ajax.

public function isAjax() {
        return isset($_SERVER['HTTP_X_REQUESTED_WITH']) && $_SERVER['HTTP_X_REQUESTED_WITH'] === 'XMLHttpRequest';
}
 3
Author: Nanhe Kumar, 2018-01-17 13:30:20

Из PHP 7 с нулевым оператором объединения он будет короче:

$is_ajax = 'XMLHttpRequest' == ( $_SERVER['HTTP_X_REQUESTED_WITH'] ?? '' );
 1
Author: Emeszenes, 2018-05-11 06:32:47

Вы можете попробовать использовать переменную $_SESSION, чтобы убедиться, что запрос был сделан из браузера. В противном случае вы могли бы отправить запрос через базу данных или файл [на стороне сервера].

 -3
Author: Static Cast, 2013-08-15 19:53:36