如何检查请求是否是PHP的AJAX请求

Bac*_*ash 49 php ajax xmlhttprequest

如果对我的php页面的请求是ajax请求,我想检查服务器端.

我看到了两种方法:

第一种方式:GET在请求中发送一个参数,告诉页面这是一个AJAX请求(= mypage.php?ajax)

mypage.php:

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

第二种方式:设置标题为xmlHttpRequest:

客户端js:

xmlHttpRequestObject.open(“GET”,url,true);
xmlHttpRequestObject.setRequestHeader('X-Requested-With', 'XMLHttpRequest');
Run Code Online (Sandbox Code Playgroud)

mypage.php:

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

事实是,这两种方式很容易被黑客攻击,因此检查我是否收到这样的AJAX请求是不安全的.

如何检查我是否收到了AJAX请求?

Vol*_*myr 55

这是实现结果的教程.

例:

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

这将检查HTTP_X_REQUESTED_WITH参数是否为空并且如果它等于xmlhttprequest,则它将退出脚本.

  • 2021 年你好,如果用户使用 jQuery ajax,例如“.ajax()”、“.post()”,但使用普通 JS“XMLHttpRequest()”或“.fetch()”,则此代码可以正常工作。不再发送此标头。 (6认同)
  • 这个答案现在非常相关,因为facebook安卓应用程序使用`HTTP_X_REQUESTED_WITH = com.facebook.katana发送.添加最后一次检查`=='xmlhttprequest'.你需要用新的Facebook浏览器实现这种类型检查,否则奇怪的事情可能发生. (4认同)
  • AFAIK` $ _SERVER ['HTTP_X_REQUESTED_WITH']`可以被欺骗,所以你不会确定它是一个AJAX请求.无论如何这是一个非常糟糕的答案,请查看[如何回答](http://stackoverflow.com/questions/how-to-answer):***为链接提供上下文*** - *指向潜在解决方案的链接总是受欢迎,但请在链接周围添加上下文,以便您的同行用户可以知道它是什么以及它为什么存在.****总是引用重要链接中最相关的部分,以防目标网站无法访问或永久离线.*** (3认同)
  • 我经常使用它作为抓取工具应对的额外障碍,它并不是万无一失的,但在某些情况下它是有效的......由于 `$_SERVER['HTTP_X_REQUESTED_WITH']` 可能未定义,我建议稍微编辑一下。`if(!isset($_SERVER['HTTP_X_REQUESTED_WITH']) || strtolower($_SERVER['HTTP_X_REQUESTED_WITH']) != 'xmlhttprequest')`... (3认同)

Way*_*tty 32

没有确定的方法可以通过Ajax了解请求.您永远不会信任来自客户端的数据.您可以使用几种不同的方法,但可以通过欺骗轻松克服它们.

  • @BackSlash你可以让它变得棘手,但那将是通过默默无闻的安全性.就个人而言,我不会依赖它.您最好的选择可能是每个请求更改的令牌.或验证码. (5认同)

Gov*_*der 8

为您网站上的每个页面(实际页面不包括或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>
Run Code Online (Sandbox Code Playgroud)

然后在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;
?>
Run Code Online (Sandbox Code Playgroud)

编辑:按照我的方式设置nonce仅适用于一小时并且更改,因此如果他们没有刷新在最后一小时或2中执行ajax调用的页面,则ajax请求将失败.

  • 这更像是一种 CSRF 保护,而不是一种确定它是常规 GET/POST 请求还是 ajax 请求的方法。 (2认同)

Nan*_*mar 6

此函数在yii框架中用于ajax调用检查.

public function isAjax() {
        return isset($_SERVER['HTTP_X_REQUESTED_WITH']) && $_SERVER['HTTP_X_REQUESTED_WITH'] === 'XMLHttpRequest';
}
Run Code Online (Sandbox Code Playgroud)

  • 不在ii中,此代码适用于所有框架 (2认同)

rev*_*oke 5

$headers = apache_request_headers();
$is_ajax = (isset($headers['X-Requested-With']) && $headers['X-Requested-With'] == 'XMLHttpRequest');
Run Code Online (Sandbox Code Playgroud)


小智 5

从具有空合并运算符的PHP 7开始,它会更短:

$is_ajax = 'XMLHttpRequest' == ( $_SERVER['HTTP_X_REQUESTED_WITH'] ?? '' );
Run Code Online (Sandbox Code Playgroud)