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

IT技术 javascript php jquery ajax cors
2021-01-14 15:34:53

我正在一个平台上对我自己的服务器进行 ajax 调用,该平台设置为阻止这些 ajax 调用(但我需要它从我的服务器获取数据以显示从我的服务器数据库中检索到的数据)。我的 ajax 脚本正在运行,它可以将数据发送到我服务器的 php 脚本以允许它进行处理。但是它无法取回已处理的数据,因为它被阻止了"Access-Control-Allow-Origin"

我无法访问该平台的源代码/核心。所以我无法删除它不允许我这样做的脚本。(P/SI 使用 Google 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);

      } 
  });

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

我希望有人可以帮助我。

6个回答

把它放在retrieve.php之上:

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

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

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

请参阅以下堆栈答案以更好地理解 Access-Control-Allow-Origin

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

tnx,但您不应该允许访问@RobQuist 在他的评论中提到的所有来源,并且在他的回答中提供了更好的方法
2021-03-13 15:34:53
@ShawnWhinnery 这基本上是“代理”的行为。如果您真的想从您无法控制的另一个网站动态加载数据,那么这是一个很好的解决方案。
2021-03-22 15:34:53
想从 dotnet 核心运行 PHP 脚本 - 将 php 脚本移动到我的另一个 URL,但出现跨站点脚本错误。将您显示的代码添加到 PHP 顶部并完美运行。谢谢!
2021-03-29 15:34:53
那比较不安全。在底部查看我的答案。
2021-04-01 15:34:53
所以我找到了这个页面,因为我需要真正“绕过”服务器上的访问控制。这里的解决方案不是绕过任何东西,而只是在他自己的服务器上正确配置访问控制。如果有人真的需要绕过这个,他们可以使用 PHP 的 file_get_contents($remote_url);。显然有很多方法可以做到这一点,但这就是我所做的。
2021-04-05 15:34:53

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

您想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请求并在某人的 facebook 上发布数据 - 就在他们浏览您的网站时。

使用ACAO标题时要非常小心

@Sanimal & lewsid -> 我猜逗号分隔确实不起作用。参考:w3.org/TR/cors
2021-03-13 15:34:53
可悲的是,这似乎不起作用。我相信每次调用 header() 只能提供一个异常。
2021-03-28 15:34:53
我认为您需要将 http:// 放在列表中的每个项目的前面。至少我为我正在处理的一个网站做了。
2021-03-29 15:34:53
添加 4 个这样的标头是毫无意义的,因为每次调用都会header()替换相同类型的前一个标头。所以实际上你所做的就是设置最后一个标题。手动输入状态,您可以设置第二个参数false,以防止一个头被覆盖。
2021-03-30 15:34:53
对于处理域列表,这里有一个相关的答案:stackoverflow.com/a/1850482/766177
2021-04-04 15:34:53

警告,如果您遵循其他一些答案,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");
}
这是一个比我发布的更好的解决方案。
2021-03-14 15:34:53

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

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

在我之前

return Json(model, JsonRequestBehavior.AllowGet);

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

希望有帮助。

使用 是一个非常糟糕的主意*,这让您对跨站点脚本开放态度。您基本上一直都希望拥有自己的域,范围限于当前的 SSL 设置,以及可选的其他域。您还希望它们都作为一个标头发送。以下内容将始终在与当前页面相同的 SSL 范围内授权您自己的域,并且还可以选择包含任意数量的附加域。它会将它们全部作为一个标头发送,如果其他东西已经发送它们,则覆盖前一个(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.
    }
}

用法:

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

你明白了。