Обнаружив Ajax в PHP и убедившись, что запрос был с моего собственного сайта - PullRequest
46 голосов
/ 23 декабря 2009

Я использую свой PHP-бэкэнд для обнаружения AJAX-запросов, проверяя значение в $_SERVER['HTTP_X_REQUESTED_WITH'].

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

Как я могу убедиться, что запрос пришел с моего собственного домена, а не с внешнего домена / робота?

www.example.com / ajax? True может позволить любому сделать вызов AJAX и сократить информацию.

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

Имеет ли это значение в наши дни?

Ответы [ 7 ]

32 голосов
/ 23 декабря 2009

Пусть вам контроллер

  • создать токен доступа
  • сохранить в сеансе для последующего сравнения

По вашему мнению

  • объявить токен доступа как переменную JS
  • отправлять токен с каждым запросом

Назад в вашем контроллере

  • проверить HTTP_X_REQUESTED_WITH
  • проверка токена

Ознакомьтесь с этими рекомендациями по безопасности от OpenAjax .
Кроме того, прочитайте статью на codinghorror.com Энни по ссылке.

23 голосов
/ 23 декабря 2009

Вы можете проверить HTTP_REFERRER, но не все браузеры установили его. Лучший способ - написать оболочку для ваших вызовов ajax на стороне JavaScript, которая отправляет часть document.cookie обратно на сервер - только ваш домен имеет доступ к cookie. Вы можете сравнить cookie в заголовках запроса с cookie в вызове AJAX в php.

В ответ на это "имеет ли это значение в наши дни" - ДА, это так! Читать это .

6 голосов
/ 23 декабря 2009

Относительно вашего последнего вопроса: "Имеет ли это значение в наши дни?" Это вопрос в каждом конкретном случае. Если запрос ajax делает что-то, что не требует защиты (например, загрузка последних котировок акций), то это действительно не имеет значения ИМХО. Если запрос загружает информацию, которая должна быть защищена (например, возвращает идентифицирующую информацию или делает что-то на сервере), то вы должны обращаться с ней как с таковой.

Лично я не использую переменные сервера, чтобы знать, когда что-то является запросом ajax. Вместо этого я просто добавляю параметр запроса к вызову ajax (например, http://domain.com/?ajax=true).. Если мне нужно защитить вызов ajax, я бы использовал те же методы, что и для обеспечения обычного запроса страницы (с использованием как клиента, так и сервера). Как Лукас Оман указал, что все на стороне клиента может быть подделано. В итоге не доверяйте ни одному запросу, даже если вы думаете, что он поступает с вашего сайта или из базы данных. Всегда следуйте мантре «фильтр ввода - выходной выход».

3 голосов
/ 23 декабря 2009

У Дэвида Уолша есть хорошее решение

/* decide what the content should be up here .... */
$content = get_content(); //generic function;

/* AJAX check  */
if(!empty($_SERVER['HTTP_X_REQUESTED_WITH']) && strtolower($_SERVER['HTTP_X_REQUESTED_WITH']) == 'xmlhttprequest') {
    /* special ajax here */
    die($content);
}

/* not ajax, do more.... */
2 голосов
/ 23 декабря 2009

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

Конечно, кто-то еще может перехватить идентификатор сеанса, но если вы также сохраняете IP-адрес пользователя в своем сеансе и проверяете его при каждом запросе, вы можете отсеять много угонов. Только кто-то в той же локальной сети или прокси может его взломать.

Любой другой упомянутый метод - cookie, javascript, http referer - зависит от данных на стороне клиента, которые небезопасны и всегда должны подозреваться в том, что они являются фальшивыми, поддельными, похищенными и злонамеренно сконструированными.

1 голос
/ 12 февраля 2016

Использовать запросы, защищенные сеансом POST:

Внутри веб-страницы (например, index.php) нам нужно сохранить идентификатор сеанса

<?php
// Create Session
$session = session_id();
if(empty($session)) session_start();
?>
<head>
...
<script type="text/javascript">
  sid = '<?php echo session_id(); ?>';
</script>
<script type="text/javascript" src="ajaxrequest.js"></script>
...
</head>

Ajax-запросы (ajaxrequest.js)

/* simple getAjax function 
 * @param $url       request url
 * @param $param     parameter (dont use ?)
 * @param callback  function on success
 */
var spinnerid = '#spinner'; // Spinner as long ajax requests running
$(document).ajaxStart(function() { $(spinnerid).show(); });
$(document).ajaxStop(function() { $(spinnerid).hide(); });
function getAjax( url, param, callback ) {
    var data = null;
    url += "?sid=" + sid + "&" + param;
    $.ajax({
        url: url,
        method: "POST", // uncomment to use GET, POST is secured by session
        cache: false,
        async: true,
        success : function(data){
      callback(data);
    },
}

getAjax( 'http://domain.com/', 'data=foo', function( data ) {
 // do stuf with data 
 var jsonobj = eval("(" + data + ")");
 var data = jsonobj[0][ 'data' ];
});

Ответственная сторона php:

if( isset( $_GET['sid'] ) ) $client_sid = $_GET['sid'];

if( session_id() == null ) session_start();

if( session_id() != $client_sid ) {
    // noID or wrongID, redirect to mainindex
    ignore_user_abort(true);
    header( "HTTP/1.1 403 Forbidden" );
    header("Connection: close", true);
    exit;
} else {

    // get data
    if( isset( $_GET['data'] ) ) {
        $data = $_GET['data'];
    } else if( isset( $_POST['data'] ) ) {
        $data = $_POST['data'];
    } else {
        $data = null;
    }

    // do stuff with data

    // return data as json
    $resp[0]['data'] = $data; 
    print_r( json_encode( $resp ) );
}
0 голосов
/ 23 декабря 2009

Отметьте $_SERVER['HTTP_REFERER']. Это будет работать во многих случаях, но его не следует путать с полностью безопасным решением.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...