Access-Control-Allow-Origin ошибка в расширении Chrome - PullRequest
1 голос
/ 04 февраля 2012

У меня есть расширение Chrome, которое специальным образом отслеживает браузер, отправляя некоторые данные на веб-сервер. В текущей конфигурации это localhost. Таким образом, скрипт контента содержит такой код:

var xhr = new XMLHttpRequest();
xhr.onreadystatechange = function(data)...
xhr.open('GET', url, true);
xhr.send();

где параметр url равен 'http://localhost/ctrl?params' (или http://127.0.0.1/ctrl?params - это не имеет значения).

Manifest-файл содержит все необходимые разрешения для межсайтовых запросов.

Расширение отлично работает на большинстве сайтов, но на одном сайте я получаю сообщение об ошибке:

XMLHttpRequest cannot load http://localhost/ctrl?params. Origin http://www.thissite.com is not allowed by Access-Control-Allow-Origin.

Я пробовал несколько разрешений, которые предлагаются здесь (*://*/*, http://*/* и <all_urls>), но никто не помог решить проблему.

Итак, вопрос в том, что может быть не так с этим конкретным сайтом (по-видимому, могут быть другие сайты с похожим поведением, и я хотел бы знать природу этого), и как исправить ошибку?

Ответы [ 2 ]

10 голосов
/ 12 февраля 2012

(tl; dr: см. Два возможных обходных пути в конце ответа)

Это последовательность событий, которая приводит к тому поведению, которое вы видите:

  1. http://www.wix.com/ начинает загружаться
  2. У него есть тег <script>, который асинхронно загружает скрипт Facebook Connect:
    (function() {
      var e = document.createElement('script');
      e.type = 'text/javascript';
      e.src = document.location.protocol +
        '//connect.facebook.net/en_US/all.js';
      e.async = true;
      document.getElementById('fb-root').appendChild(e);
    }());
    
  3. После HTML (но не ресурсы, включая Facebook Connect)скрипт) страницы wix.com загружается, событие DOMContentLoaded срабатывает.Поскольку ваш скрипт контента использует "run_at" : "document_end", он вставляется и запускается в это время.
  4. Ваш скрипт контента запускает следующий код (насколько я могу сказать, он хочет выполнить большую часть своей работы послеload событие запускается):
    window.onload = function() {
      // code that eventually does the cross-origin XMLHttpRequest
    };
    
  5. Загружается скрипт Facebook Connect, и он имеет свой собственный обработчик событий load, который добавляется с помощью этого фрагмента:
    (function() {
      var oldonload=window.onload;
      window.onload=function(){
        // Run new onload code
        if(oldonload) {
          if(typeof oldonload=='string') {
            eval(oldonload);
          } else {
            oldonload();
          }
        }
      };
    })();
    
    (это первая ключевая часть) Поскольку ваш скрипт установил свойство onload, oldonload является обработчиком загрузки вашего скрипта.
  6. В конечном итоге все ресурсы загружаются, и обработчик событий load срабатывает.
  7. Обработчик load Facebook Connect запускается, который запускает свой собственный код, а затем вызывает oldonload.(это вторая ключевая часть) Поскольку страница вызывает ваш обработчик load, она запускается не в изолированном мире вашего скрипта , а в "главном мире" страницы .Только изолированный мир скрипта имеет перекрестный доступ XMLHttpRequest, поэтому запрос не выполнен.

Чтобы увидеть упрощенный тестовый пример этого, см. this page (что имитирует http://www.wix.com),, который загружает этот скрипт (который имитирует Facebook Connect). Я также выложил упрощенные версии скрипта контента и манифеста расширения .

Тот факт, что ваш обработчик load работает в «основном мире», скорее всего, является проявлением Chrome bug 87520 (ошибка имеет последствия для безопасности, так что вы можете неможет видеть это).

Есть два способа обойти это:

  1. Вместо использования "run_at" : "document_end" и обработчика событий load, вы можете использовать запуск по умолчаниювремя (document_idle, после загрузки документа) и просто включите свой код.
  2. Вместо добавления обработчика событий load путем установки свойства window.onload используйте window.addEventListener('load', func).обработчик событий не будет виден на Facebook Connect, поэтому яЗапустится в изолированном мире скрипта контента.
1 голос
/ 07 февраля 2012

Видимая проблема источника контроля доступа, скорее всего, проявляется в заголовках ответа (вне вашего контроля), а не в запросе (под вашим контролем).

Access-Control-Allow-Origin - это политика для CORS , установленная в заголовке.Например, используя PHP, вы используете набор заголовков, таких как следующие, чтобы включить CORS:

header('Access-Control-Allow-Origin: http://blah.com');
header('Access-Control-Allow-Credentials: true' );
header('Access-Control-Allow-Headers: Content-Type, Content-Disposition, attachment');

Если звучит так, если сервер задает конкретное начало в этом заголовке, тогда ваш Chromeрасширение следует директиве, разрешающей междоменные (POST?) запросы только из этого домена.

...