web-dev-qa-db-ja.com

CORBがCORSヘッダーで応答するデータリソースへのリクエストをブロックしないようにするにはどうすればよいですか?

特定のウェブサイトから自分が制御するAPIにリクエストを送信するChrome拡張機能を開発しています。 Chrome 73まで、拡張機能は正しく機能していました。 Chrome 73にアップグレードした後、次のエラーが発生し始めました:

Cross-Origin Read Blocking(CORB)blocked cross cross Origin response http:// localhost:3000/api/users/1 with MIME type application/json

CORBに関するChromeのドキュメント によると、CORBは次のすべてが当てはまる場合、リクエストの応答をブロックします。

  1. リソースは「データリソース」です。具体的には、コンテンツタイプはHTML、XML、JSONです。

  2. サーバーは_X-Content-Type-Options: nosniff_ヘッダーで応答します。このヘッダーが省略されている場合、Chromeは、ファイルの検査からコンテンツタイプがHTML、XML、またはJSONのいずれかであることを検出します

  3. CORSはリソースへのアクセスを明示的に許可しません

また、 "Lessons from Spectre and Meltdown"(Google I/O 2018) によると、fetch呼び出しに_mode: cors_を追加することが重要であると思われます。 、 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によってリクエストがブロックされないようにするために何を変更できますか?

14
Ceasar Bautista

"クロスオリジンリクエストの変更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 Responseオブジェクトを背景ページから拡張機能に単に渡すことはできません。)

バックグラウンドページはCORSまたはCORBの影響を受けないため、ブラウザはAPIからの応答をブロックしなくなりました。

14
Ceasar Bautista

一時的な解決策:コマンドブラウザーを実行してCORBを無効にします--disable-features=CrossSiteDocumentBlockingAlways,CrossSiteDocumentBlockingIfIsolating

Linuxでのrunコマンドの例。

Chromeの場合:

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

クロムの場合:

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

同様の質問

ソース

1
Epexa

https://www.chromium.org/Home/chromium-security/extension-content-script-fetches を参照してください

セキュリティを強化するために、Chrome Extensions)のコンテンツスクリプトからクロスオリジンフェッチがすぐに禁止されます。このようなリクエストは、拡張機能のバックグラウンドページから行うことができ、必要に応じてコンテンツスクリプトにリレーできます。

クロスオリジンを回避するためにそれを行うことができます。

古いコンテンツスクリプト、クロスオリジンフェッチを作成:

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.
    }
  });
0
李方郑