как обойти Access-Control-Allow-Origin?

Я делаю вызов 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 разрешено.

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

8 ответов


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

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

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

неправильно

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

правильно

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

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

вы хотели бы отправить несколько 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-заголовки can быть обманутым, но этот заголовок предназначен для защиты клиента. Не защищайте свои данные этими значениями. Если вы хотите узнать больше, прочитайте немного о CORS и CSRF.

почему это безопаснее?

разрешение доступа из других мест, то ваш собственный надежный сайт позволяет для сеанса highjacking. Я собираюсь пойти с небольшим примером-изображение Facebook позволяет происхождение подстановочного знака - это означает, что вы можете сделать свой собственный веб-сайт где-нибудь, и заставить его запускать AJAX-вызовы (или открывать iframes) на facebook. Это означает, что вы можете захватить зарегистрированную информацию о facebook посетителя вашего сайта. Еще хуже-вы можете script POST запросы и размещать данные на чей-то facebook - пока они просматривают ваш сайт.

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


предупреждение, 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");
}

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

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

перед моими

return Json(model, JsonRequestBehavior.AllowGet);

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

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


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

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

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


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

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


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