如何绕过Access-Control-Allow-Origin?

时间:2011-09-27 06:03:13

标签: javascript php jquery ajax cors

我在他们设置的平台上对我自己的服务器进行ajax调用,防止这些ajax调用(但我需要它从我的服务器获取数据以显示从我服务器的数据库中检索的数据)。 我的ajax脚本正在运行,它可以将数据发送到我服务器的php脚本以允许它处理。 但是,由于"Access-Control-Allow-Origin"

阻止了处理后的数据,因此无法将其恢复

我无法访问该平台的源/核心。所以我无法删除它禁止我这样做的脚本。 (P / S我使用谷歌Chrome控制台并发现了这个错误)

Ajax代码如下所示:

 $.ajax({
     type: "GET",
     url: "http://example.com/retrieve.php",
     data: "id=" + id + "&url=" + url,
     dataType: 'json',   
     cache: false,
     success: function(data)
      {
        var friend = data[1];              
        var blog = data[2];           
        $('#user').html("<b>Friends: </b>"+friend+"<b><br> Blogs: </b>"+blog);

      } 
  });

或者上面的ajax脚本是否有JSON等效代码?我认为JSON是允许的。

我希望有人可以帮助我。

7 个答案:

答案 0 :(得分:345)

将它放在retrieve.php:

之上
header('Access-Control-Allow-Origin: *');  

请注意,这会有效地禁用CORS保护,并使您的用户受到攻击。如果您不完全确定需要允许所有来源,则应将其锁定为更具体的来源:

header('Access-Control-Allow-Origin: https://www.example.com')

答案 1 :(得分:277)

好的,但是你们都知道*是一个通配符并允许来自每个域的跨站点脚本?

您希望为每个允许访问的网站发送多个Access-Control-Allow-Origin标头,但遗憾的是,它们不支持发送多个Access-Control-Allow-Origin标头,或者放置多个来源。

您可以通过检查原点来解决此问题,并在标题中发回一个,如果允许的话:

$origin = $_SERVER['HTTP_ORIGIN'];
$allowed_domains = [
    'http://mysite1.com',
    'https://www.mysite2.com',
    'http://www.mysite2.com',
];

if (in_array($origin, $allowed_domains)) {
    header('Access-Control-Allow-Origin: ' . $origin);
}

这样更安全。您可能希望编辑匹配并将其更改为具有某些正则表达式的手动函数,或类似的东西。至少这只会发回1个标题,你将确定它是请求来自的标题。请注意,所有HTTP标头都可以被欺骗,但此标头是为了客户端的保护。不要使用这些值保护您自己的数据。如果您想了解更多信息,请阅读CORS和CSRF。

为什么它更安全?

允许从其他位置访问,然后您自己的可信站点允许会话劫持。我将用一个小例子 - 图片Facebook允许一个通配符来源 - 这意味着你可以在某个地方创建自己的网站,并让它向Facebook发起AJAX调用(或打开iframe)。这意味着您可以获取您网站访问者的Facebook的登录信息。更糟糕的是 - 您可以编写POST个请求并在某人的脸书上发布数据 - 就在他们浏览您的网站时。

使用ACAO标题时要非常谨慎!

答案 2 :(得分:30)

警告,Chrome(和其他浏览器)会抱怨如果您按照其他一些答案设置了多个ACAO标头。

错误类似于 XMLHttpRequest cannot load ____. The 'Access-Control-Allow-Origin' header contains multiple values '____, ____, ____', but only one is allowed. Origin '____' is therefore not allowed access.

试试这个:

$http_origin = $_SERVER['HTTP_ORIGIN'];

$allowed_domains = array(
  'http://domain1.com',
  'http://domain2.com',
);

if (in_array($http_origin, $allowed_domains))
{  
    header("Access-Control-Allow-Origin: $http_origin");
}

答案 3 :(得分:7)

我在调用MVC3控制器时修复了这个问题。 我补充说:

Response.AddHeader("Access-Control-Allow-Origin", "*"); 

之前

return Json(model, JsonRequestBehavior.AllowGet);

而且我的$.ajax抱怨它在我的ajax调用中不接受 Content-type 标头,因此我将其注释掉,因为我知道它的JSON传递给了Action。

希望有所帮助。

答案 4 :(得分:5)

最好是允许单个域名,请注意http://:

     header('Access-Control-Allow-Origin: http://www.foo.com', false);
     header('Access-Control-Allow-Origin: http://www.foo2.com', false));

答案 5 :(得分:2)

您是否尝试过将Access-Control-Allow-Origin标头添加到服务器发送的响应中?比如,Access-Control-Allow-Origin: *

答案 6 :(得分:0)

使用*是一个非常糟糕的主意,这使您可以对跨站点脚本进行全面开放。您基本上一直希望拥有自己的域,范围限制为当前的SSL设置,以及可选的其他域。您还希望将它们全部作为一个标头发送。以下内容将始终在与当前页面相同的SSL作用域中授权您自己的域,并且还可以选择包含任意数量的其他域。它会将它们全部作为一个标头发送,如果已经发送了其他内容,则覆盖前一个标题,以避免浏览器抱怨发送多个访问控制标头。

class CorsAccessControl
{
    private $allowed = array();

    /**
     * Always adds your own domain with the current ssl settings.
     */
    public function __construct()
    {
        // Add your own domain, with respect to the current SSL settings.
        $this->allowed[] = 'http'
            . ( ( array_key_exists( 'HTTPS', $_SERVER )
                && $_SERVER['HTTPS'] 
                && strtolower( $_SERVER['HTTPS'] ) !== 'off' ) 
                    ? 's' 
                    : null )
            . '://' . $_SERVER['HTTP_HOST'];
    }

    /**
     * Optionally add additional domains. Each is only added one time.
     */
    public function add($domain)
    {
        if ( !in_array( $domain, $this->allowed )
        {
            $this->allowed[] = $domain;
        }
    /**
     * Send 'em all as one header so no browsers grumble about it.
     */
    public function send()
    {
        $domains = implode( ', ', $this->allowed );
        header( 'Access-Control-Allow-Origin: ' . $domains, true ); // We want to send them all as one shot, so replace should be true here.
    }
}

用法:

$cors = new CorsAccessControl();

// If you are only authorizing your own domain:
$cors->send();

// If you are authorizing multiple domains:
foreach ($domains as $domain)
{
    $cors->add($domain);
}
$cors->send();

你明白了。