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

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

185 голосов
/ 27 сентября 2011

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

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

Ответы [ 7 ]

349 голосов
/ 27 сентября 2011

Поместите это поверх retrieve.php:

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

Обратите внимание, что это эффективно отключает защиту CORS и оставляет ваших пользователей уязвимыми для атак. Если вы не совсем уверены, что вам нужно разрешить все происхождение, вы должны зафиксировать это для более конкретного происхождения:

header('Access-Control-Allow-Origin: https://www.example.com')
279 голосов
/ 14 июня 2013

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

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

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

30 голосов
/ 10 января 2017

Предупреждение , 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");
}
7 голосов
/ 19 марта 2012

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

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

до моего

return Json(model, JsonRequestBehavior.AllowGet);

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

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

5 голосов
/ 18 апреля 2014

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

     header('Access-Control-Allow-Origin: http://www.foo.com', false);
     header('Access-Control-Allow-Origin: http://www.foo2.com', false));
2 голосов
/ 27 сентября 2011

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

0 голосов
/ 23 апреля 2018

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

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

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...