Как запретить CORB блокировать запросы к ресурсам данных, которые отвечают заголовками CORS? - PullRequest
6 голосов
/ 18 марта 2019

Я занимаюсь разработкой расширения для Chrome, которое отправляет запросы с определенных веб-сайтов на API, которым я управляю. До Chrome 73 расширение работало корректно. После обновления до Chrome 73 я начал получать следующую ошибку:

Блокировка перекрестного происхождения (CORB) заблокировала ответ перекрестного происхождения http://localhost:3000/api/users/1 с приложением типа MIME / JSON

В соответствии с документацией Chrome по CORB , CORB заблокирует ответ на запрос, если выполнено все следующее:

  1. Ресурс является «ресурсом данных». В частности, тип контента: HTML, XML, JSON

  2. Сервер отвечает заголовком X-Content-Type-Options: nosniff, или, если этот заголовок пропущен, Chrome обнаруживает, что тип содержимого является одним из HTML, XML или JSON для проверки файла

  3. CORS явно не разрешает доступ к ресурсу

Кроме того, в соответствии с «Уроками призрака и распада» (Google I / O 2018) может показаться важным добавить mode: cors к fetch вызовам, то есть fetch(url, { mode: 'cors' }).

Чтобы попытаться это исправить, я внес следующие изменения:

Сначала я добавил следующие заголовки ко всем ответам из моего API:

Access-Control-Allow-Credentials: true
Access-Control-Allow-Headers: Content-Type
Access-Control-Allow-Methods: GET, POST
Access-Control-Allow-Origin: https://www.example.com

Во-вторых, я обновил мой fetch() вызов для расширения, чтобы он выглядел следующим образом:

fetch(url, { credentials: 'include', mode: 'cors' })

Однако эти изменения не сработали. Что можно изменить, чтобы CORB не блокировал мой запрос?

Ответы [ 3 ]

10 голосов
/ 18 марта 2019

На основании примеров в "Изменения в перекрестных запросах в скриптах содержимого расширений Chrome" я заменил все вызовы fetch новым методом fetchResource, который имеет аналогичный API,но делегирует вызов fetch на фоновую страницу:

// contentScript.js
function fetchResource(input, init) {
  return new Promise((resolve, reject) => {
    chrome.runtime.sendMessage({input, init}, messageResponse => {
      const [response, error] = messageResponse;
      if (response === null) {
        reject(error);
      } else {
        // Use undefined on a 204 - No Content
        const body = response.body ? new Blob([response.body]) : undefined;
        resolve(new Response(body, {
          status: response.status,
          statusText: response.statusText,
        }));
      }
    });
  });
}

// background.js
chrome.runtime.onMessage.addListener(function(request, sender, sendResponse) {
  fetch(request.input, request.init).then(function(response) {
    return response.text().then(function(text) {
      sendResponse([{
        body: text,
        status: response.status,
        statusText: response.statusText,
      }, null]);
    });
  }, function(error) {
    sendResponse([null, error]);
  });
  return true;
});

Это наименьший набор изменений, которые я смог внести в свое приложение, чтобы исправить проблему.(Обратите внимание, что расширения и фоновые страницы могут передавать между ними только JSON-сериализуемые объекты, поэтому мы не можем просто передать объект ответа Fetch API с фоновой страницы на расширение.)

На фоновые страницы не влияет CORS илиCORB, поэтому браузер больше не блокирует ответы от API.

1 голос
/ 25 марта 2019

Временное решение: отключить CORB с помощью браузера команд запуска --disable-features=CrossSiteDocumentBlockingAlways,CrossSiteDocumentBlockingIfIsolating

Пример команды запуска в Linux.

Для Chrome:

chrome %U --disable-features=CrossSiteDocumentBlockingAlways,CrossSiteDocumentBlockingIfIsolating

Для хрома:

chromium-browser %U --disable-features=CrossSiteDocumentBlockingAlways,CrossSiteDocumentBlockingIfIsolating

Аналогичный вопрос.

Источник .

0 голосов
/ 22 марта 2019

См. https://www.chromium.org/Home/chromium-security/extension-content-script-fetches

В целях повышения безопасности скоро будут запрещены выборки из разных источников в сценариях содержимого в расширениях Chrome. Такие запросы могут быть сделаны из фоновых страниц расширений и при необходимости переданы в скрипты содержимого.

Вы можете сделать это, чтобы избежать перекрестного происхождения.

Старый скрипт содержимого с извлечением из разных источников:

var itemId = 12345;
var url = "https://another-site.com/price-query?itemId=" +
         encodeURIComponent(request.itemId);
fetch(url)
  .then(response => response.text())
  .then(text => parsePrice(text))
  .then(price => ...)
  .catch(error => ...)

Новый скрипт содержимого, запрашивающий его фоновую страницу для получения данных:

chrome.runtime.sendMessage(
    {contentScriptQuery: "queryPrice", itemId: 12345},
    price => ...);

Новое расширение фоновой страницы, выборка с известного URL и передача данных:

chrome.runtime.onMessage.addListener(
  function(request, sender, sendResponse) {
    if (request.contentScriptQuery == "queryPrice") {
      var url = "https://another-site.com/price-query?itemId=" +
              encodeURIComponent(request.itemId);
      fetch(url)
          .then(response => response.text())
          .then(text => parsePrice(text))
          .then(price => sendResponse(price))
          .catch(error => ...)
      return true;  // Will respond asynchronously.
    }
  });
...