如何防止跨域Ajax请求?

| 如何检测是否从另一个域调用了我的PHP脚本,并且另一个域正在非法使用我的脚本?有没有办法防止这种情况? 更新 我在SO上发现了这个问题,但它仍然不安全,可以被欺骗。     
已邀请:
        没有任何绝对安全的方法可以防止这种情况发生,因为可以欺骗任何标头信息。基于会话的令牌是另一种可能的解决方案,但是在这种情况下,您的javascript是可以公开访问的,因此任何想花一点时间的人都可以确定您的令牌系统的工作方式,并找到解决方案。 多种方法的组合将为您提供最广泛的保护。您可以查找标题,使用和.htaccess文件以及使用令牌。这种全面的方法使滥用Web服务器变得更加困难-大多数滥用来自试图找到容易利用的漏洞的人们。要记住的重要一点是,您不会因为已经部署了“最佳”保护措施而感到自满,或者因为您拥有太多保护层而似乎无法破解。如果有人真的想要它足够糟糕并有时间,他们会找到方法。这些类型的预防措施实际上只能阻止那些懒惰,好奇和无所事事的恶意软件。有针对性的攻击是一整套单独的安全性,通常更集中于服务器级安全性问题。 样本htaccess。这不是您要放在根目录中的内容,而是放在一个子文件夹中,该子文件夹中的脚本永远不应从地址栏中调用:
RewriteEngine on
RewriteCond %{HTTP_REFERER} !^$
RewriteCond %{HTTP_REFERER} !^http(s)?://(www\\.)?_YOUR_DOMAIN_NAME_HERE.com [NC]
RewriteRule \\.(php)$ - [NC,F,L]
请查看此文章以获取有关使用令牌系统的信息:https://www.owasp.org/index.php/Cross-Site_Request_Forgery_%28CSRF%29_Prevention_Cheat_Sheet     
        您可以手动拒绝每个
Origin
标头与您的域名不匹配的请求。但是,并非所有浏览器都发送
Origin
标头。在这些情况下,您可以回退到
Referer
[sic]标头,进行解析并找出域名,然后如上所述进行比较。 一些JavaScript框架还为AJAX请求设置了“ 4”头。 这应该会拒绝很大一部分用户(我估计> 95%)。请注意,由于“同源策略”,向您的域发送AJAX请求的家伙唯一获得的就是定时信息。     
        有点像建议的user3491125一样,您可以在进行调用的页面中设置$ _SESSION,并在Ajax页面上检查它,例如是否设置了$ _SESSION [\'user \']。     
        对于user3491125的答案,您可以尝试加密会话令牌。我有一个加密功能,可以基于用户端口80 IP添加唯一密钥。它并非万无一失,但确实使黑客更加困难。
function encryptString($string, $action, $baseIP = \'false\', $extraKey = \'\'){
    global $flag;

    $encryptedIP = \'\';

    if($baseIP){
        $encryptedIP = encryptString(strip_tags(htmlentities($_SERVER[\'REMOTE_ADDR\'])), \'encrypt\', false);
    }

    $output = false;

    $encrypt_method = \"AES-256-CBC\";
    $secret_key = $flag[\'encrypt-key\'].$encryptedIP.\'-\'.$extraKey;
    $secret_iv = $flag[\'encrypt-secret\'].$encryptedIP.\'-\'.$extraKey;

    $key = hash(\'sha256\', $secret_key);
    $iv = substr(hash(\'sha256\', $secret_iv), 0, 16);

    $output;

    if($action == \'encrypt\'){
        $output = openssl_encrypt($string, $encrypt_method, $key, 0, $iv);
        $output = base64_encode($output);
        $output = str_replace(\'=\', \'[equal]\', $output);
    }else if($action == \'decrypt\'){
        $setString = str_replace(\'[equal]\', \'=\', $string);
        $output = openssl_decrypt(base64_decode($setString), $encrypt_method, $key, 0, $iv);
    }

    return $output;
}
    
        这不是可以解决的问题。如果您创建一个网站,那么根据定义,您将使其公开可用。 如果您希望数据是私有的,则需要进行某种登录。 如果没有登录/烦扰验证码,就不可能创建一个对用户开放但对脚本不开放的系统。     
        我知道这是一篇过时的文章,但目前这里有一种“万无一失”的方法来避免这种情况,并且它像地狱一样简单... 在将进行ajax调用的页面中的第一个:
<?php
$token = sha1(rand(1000,9999)); 
$_SESSION[\'token\'] = $token;
?>
然后在ajax脚本中
var formData = new FormData();
formData.append(\"token\",\"<?php echo $token;?>\");
        $.ajax({
            url: \'yourfile.php\',
            type: \'POST\',
            xhr: function() {
                var myXhr = $.ajaxSettings.xhr();
                return myXhr; 
            },
            success:function(data) {
                alert(data);
            },
            data: formData,
            cache: false,
            contentType: false,
            processData: false
        }); 
最后在将被调用的php页面中:
<?php
$token = $_POST[\'token\'];
if($token === $_SESSION[\'token\'] && $_SERVER[\'HTTP_X_REQUESTED_WITH\'] == \'XMLHttpRequest\')
{
   //Perform your stuff here...
}
?>    
    

要回复问题请先登录注册