как обойти Контроль доступа-Разрешить-Происхождение?


Я выполняю вызов ajax на свой собственный сервер на платформе, которую они установили, чтобы предотвратить эти вызовы ajax (но мне это нужно для извлечения данных с моего сервера для отображения извлеченных данных из базы данных моего сервера). Мой скрипт ajax работает, он может отправлять данные в php-скрипт моего сервера, чтобы разрешить его обработку. Однако он не может вернуть обработанные данные, так как они заблокированы "Access-Control-Allow-Origin"

У меня нет доступа к источнику/ядру этой платформы. поэтому я не могу удалить сценарий, который запрещает мне чтобы сделать это. (P/S Я использовал консоль 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 разрешено.

Я надеюсь, что кто-нибудь сможет мне помочь.

Author: Ram Patra, 2011-09-27

8 answers

Положите его поверх retrieve.php

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

Важно отметить, что header() необходимо вызвать перед отправкой любого фактического вывода.

Неправильно

<html>
<?php
header('Access-Control-Allow-Origin: *'); 
?>

Правильный

<?php
header('Access-Control-Allow-Origin: *'); 
?>
<html>
 326
Author: Rafay, 2017-08-02 17:48:29

Хорошо, но вы все знаете, что * является подстановочным знаком и позволяет создавать межсайтовые сценарии из каждого домена?

Вы хотели бы отправить несколько заголовков 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 позволяет использовать подстановочный знак origin - это означает, что вы можете создать где-нибудь свой собственный веб-сайт и заставить его запускать вызовы AJAX (или открывать iframes) на facebook. Это означает, что вы можете получить информацию о вошедшем в facebook посетителе вашего веб-сайта. Еще хуже - вы можете писать запросы POST и публиковать данные на чьем-то facebook - просто пока они просматривают ваш сайт.

Будьте очень осторожны при использовании заголовки ACAO!

 251
Author: Rob Quist, 2018-08-01 09:59:59

Предупреждение, 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");
}
 25
Author: , 2017-01-10 12:00:14

Я исправил эту проблему при вызове контроллера MVC3. Я добавил:

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

Перед моим

return Json(model, JsonRequestBehavior.AllowGet);

А также мой $.ajax жаловался, что он не принимает заголовок типа содержимого в моем вызове ajax, поэтому я прокомментировал его, поскольку знаю, что его JSON передается в действие.

Надеюсь, это поможет.

 7
Author: Atif Rehman, 2012-03-19 14:14:33

Лучше всего было бы разрешить отдельные домены, будьте осторожны с http://:

     header('Access-Control-Allow-Origin: http://www.foo.com', false);
     header('Access-Control-Allow-Origin: http://www.foo2.com', false));
 6
Author: Sebastian Viereck, 2016-11-26 10:03:06

Пытались ли вы на самом деле добавить заголовок Access-Control-Allow-Origin в ответ, отправленный с вашего сервера? Как будто, Access-Control-Allow-Origin: *?

 3
Author: Daniel Brockman, 2011-09-27 06:07:44

Использовать * действительно плохая идея, которая оставляет вас широко открытыми для межсайтовых сценариев. По сути, вам постоянно нужен свой собственный домен, ограниченный вашими текущими настройками 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();

Вы поняли идею.

 0
Author: mopsyd, 2018-04-23 01:16:02

Если вы тестируете с локального хоста, вы также можете использовать:
header('Access-Control-Allow-Origin: http://localhost:8080', false); где 8080 - это порт, который вы тестируете.

 0
Author: Philip D., 2018-07-15 15:57:50