Подтвердить что ты не робот

Как проверить, является ли запрос 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?

4b9b3361

Ответ 1

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

Ответ 2

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

Пример:

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

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

Ответ 3

Установите переменную сеанса для каждой страницы на вашем сайте (фактические страницы не включают в себя или rpcs), которая содержит имя текущей страницы, затем в своем вызове Ajax передайте одноразовый номер с $_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>

Затем в 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;
?>

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

Ответ 4

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

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

Ответ 5

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

Ответ 6

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

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

Ответ 7

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