简体   繁体   English

如何绕过访问控制允许来源?

[英]how to bypass Access-Control-Allow-Origin?

I'm doing a ajax call to my own server on a platform which they set prevent these ajax calls (but I need it to fetch the data from my server to display retrieved data from my server's database).我正在他们设置的平台上对我自己的服务器进行 ajax 调用以防止这些 ajax 调用(但我需要它从我的服务器获取数据以显示从我的服务器数据库中检索到的数据)。 My ajax script is working, it can send the data over to my server's php script to allow it to process.我的 ajax 脚本正在运行,它可以将数据发送到我服务器的 php 脚本以允许它进行处理。 However it cannot get the processed data back as it is blocked by "Access-Control-Allow-Origin"但是它无法取回已处理的数据,因为它被"Access-Control-Allow-Origin"阻止

I have no access to that platform's source/core.我无权访问该平台的源代码/核心。 so I can't remove the script that it disallowing me to do so.所以我不能删除它不允许我这样做的脚本。 (P/SI used Google Chrome's Console and found out this error) (P/SI 使用了 Google Chrome 的 Console 发现了这个错误)

The Ajax code as shown below: 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);

      } 
  });

or is there a JSON equivalent code to the ajax script above?或者上面的 ajax 脚本是否有等效的JSON代码? I think JSON is allowed.我认为JSON是允许的。

I hope someone could help me out.我希望有人能帮助我。

Put this on top of retrieve.php:把它放在retrieve.php之上:

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

Note that this effectively disables CORS protection, and leaves your users exposed to attack.请注意,这会有效地禁用 CORS 保护,并使您的用户暴露在攻击之下。 If you're not completely certain that you need to allow all origins, you should lock this down to a more specific origin:如果您不完全确定需要允许所有来源,则应将其锁定为更具体的来源:

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

Please refer to following stack answer for better understanding of Access-Control-Allow-Origin请参阅以下堆栈答案以更好地理解Access-Control-Allow-Origin

https://stackoverflow.com/a/10636765/413670 https://stackoverflow.com/a/10636765/413670

Okay, but you all know that the * is a wildcard and allows cross site scripting from every domain?好的,但你们都知道 * 是一个通配符并允许来自每个域的跨站点脚本?

You would like to send multiple Access-Control-Allow-Origin headers for every site that's allowed to - but unfortunately its officially not supported to send multiple Access-Control-Allow-Origin headers, or to put in multiple origins.您想为每个Access-Control-Allow-Origin站点发送多个Access-Control-Allow-Origin标头 - 但不幸的是,官方不支持发送多个Access-Control-Allow-Origin标头,或放入多个来源。

You can solve this by checking the origin, and sending back that one in the header, if it is allowed:如果允许,您可以通过检查来源并在标头中发回该来源来解决此问题:

$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);
}

Thats much safer.这样就安全多了。 You might want to edit the matching and change it to a manual function with some regex, or something like that.您可能想要编辑匹配项并将其更改为带有一些正则表达式或类似内容的手动功能。 At least this will only send back 1 header, and you will be sure its the one that the request came from.至少这只会发回 1 个标头,您将确定它是请求来自的标头。 Please do note that all HTTP headers can be spoofed, but this header is for the client's protection.请注意,所有 HTTP 标头都可以被欺骗,但此标头是为了保护客户端。 Don't protect your own data with those values.不要使用这些值来保护您自己的数据。 If you want to know more, read up a bit on CORS and CSRF.如果您想了解更多信息,请阅读有关 CORS 和 CSRF 的内容。

Why is it safer?为什么更安全?

Allowing access from other locations then your own trusted site allows for session highjacking.允许从其他位置访问,然后您自己的受信任站点允许会话劫持。 I'm going to go with a little example - image Facebook allows a wildcard origin - this means that you can make your own website somewhere, and make it fire AJAX calls (or open iframes) to facebook.我将举一个小例子 - 图片 Facebook 允许使用通配符来源 - 这意味着您可以在某处创建自己的网站,并使其向 facebook 发出 AJAX 调用(或打开 iframe)。 This means you can grab the logged in info of the facebook of a visitor of your website.这意味着您可以获取您网站访问者的 Facebook 登录信息。 Even worse - you can script POST requests and post data on someone's facebook - just while they are browsing your website.更糟糕的是 - 您可以编写POST请求并在某人的 Facebook 上发布数据 - 就在他们浏览您的网站时。

Be very cautious when using the ACAO headers!使用ACAO标头时要非常小心!

Warning , Chrome (and other browsers) will complain that multiple ACAO headers are set if you follow some of the other answers.警告,如果您遵循其他一些答案,Chrome(和其他浏览器)会抱怨设置了多个 ACAO 标头。

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

Try this:试试这个:

$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");
}

I have fixed this problem when calling a MVC3 Controller.我在调用 MVC3 控制器时解决了这个问题。 I added:我补充说:

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

before my在我之前

return Json(model, JsonRequestBehavior.AllowGet);

And also my $.ajax was complaining that it does not accept Content-type header in my ajax call, so I commented it out as I know its JSON being passed to the Action.而且我的$.ajax抱怨它在我的 ajax 调用中不接受Content-type标头,所以我将它注释掉,因为我知道它的 JSON 被传递给 Action。

Hope that helps.希望有帮助。

best would be to allow single domains, be careful about the http:// : 最好的是允许单个域名,请注意http://:

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

It's a really bad idea to use * , which leaves you wide open to cross site scripting.使用*是一个非常糟糕的主意,这让您对跨站点脚本持开放态度。 You basically want your own domain all of the time, scoped to your current SSL settings, and optionally additional domains.您基本上一直想要自己的域,范围限定于您当前的 SSL 设置,以及可选的其他域。 You also want them all to be sent as one header.您还希望它们都作为一个标头发送。 The following will always authorize your own domain in the same SSL scope as the current page, and can optionally also include any number of additional domains.以下内容将始终在与当前页面相同的 SSL 范围内授权您自己的域,并且还可以选择包含任意数量的附加域。 It will send them all as one header, and overwrite the previous one(s) if something else already sent them to avoid any chance of the browser grumbling about multiple access control headers being sent.它会将它们全部作为一个标头发送,如果其他东西已经发送它们,则覆盖前一个(s)以避免浏览器抱怨发送多个访问控制标头的任何机会。

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.
    }
}

Usage:用法:

$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();

You get the idea.你明白了。

Have you tried actually adding the Access-Control-Allow-Origin header to the response sent from your server?您是否尝试将 Access-Control-Allow-Origin 标头实际添加到从您的服务器发送的响应中? Like, Access-Control-Allow-Origin: * ?例如, Access-Control-Allow-Origin: *

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM