web-dev-qa-db-ja.com

リクエストがAJAXのPHPリクエストであるかどうかを確認する方法

PHPページへのリクエストがajaxリクエストであるかどうかをサーバー側で確認したいと思います。

私はこれを行う2つの方法を見ました:

最初の方法:AJAXリクエスト(= mypage.php?ajax)であることをページに伝えるGETパラメーターをリクエストで送信する

mypage.php:

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

2番目の方法:ヘッダーを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
}

事実、これらの2つの方法は簡単にハッキングされる可能性があるため、このようなAJAXリクエストを受け取ったかどうかを確認するのは安全ではありません。

AJAXリクエストを受信して​​いるかどうかを確認するにはどうすればよいですか?

46
BackSlash

Ajaxを介してリクエストが行われたことを確実に知る方法はありません。クライアントから送られてくるデータを信頼することはできません。いくつかの異なる方法を使用できますが、スプーフィングによって簡単に克服できます。

30
Wayne Whitty

これが、結果を達成するための チュートリアル です。

例:

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

これは、HTTP_X_REQUESTED_WITHパラメーターが空でないかどうか、およびxmlhttprequestと等しいかどうかを確認し、スクリプトを終了します。

53
Volodymyr

現在のページ名を含むサイトのすべてのページ(実際のページにはincludeまたはrpcsを含まない)のセッション変数を設定し、Ajax呼び出しで$_SERVER['SCRIPT_NAME'];でソルトされたnonceを渡します

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

編集:参考までに、ノンスを設定する方法は1時間だけで良いので、最後の1時間または2でajax呼び出しを行っているページを更新していない場合、ajaxリクエストは失敗します。

8
user3002997

この関数は、yiiフレームワークでajax呼び出しチェックに使用しています。

public function isAjax() {
        return isset($_SERVER['HTTP_X_REQUESTED_WITH']) && $_SERVER['HTTP_X_REQUESTED_WITH'] === 'XMLHttpRequest';
}
6
Nanhe Kumar
$headers = Apache_request_headers();
$is_ajax = (isset($headers['X-Requested-With']) && $headers['X-Requested-With'] == 'XMLHttpRequest');
4
revoke

Null合体演算子を使用したPHP 7からは短くなります。

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

以下のコードスニペットを試してください

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