特定のウェブサイトから自分が制御する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は次のすべてが当てはまる場合、リクエストの応答をブロックします。
リソースは「データリソース」です。具体的には、コンテンツタイプはHTML、XML、JSONです。
サーバーは_X-Content-Type-Options: nosniff
_ヘッダーで応答します。このヘッダーが省略されている場合、Chromeは、ファイルの検査からコンテンツタイプがHTML、XML、またはJSONのいずれかであることを検出します
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によってリクエストがブロックされないようにするために何を変更できますか?
"クロスオリジンリクエストの変更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からの応答をブロックしなくなりました。
一時的な解決策:コマンドブラウザーを実行してCORBを無効にします--disable-features=CrossSiteDocumentBlockingAlways,CrossSiteDocumentBlockingIfIsolating
Linuxでのrunコマンドの例。
Chromeの場合:
chrome %U --disable-features=CrossSiteDocumentBlockingAlways,CrossSiteDocumentBlockingIfIsolating
クロムの場合:
chromium-browser %U --disable-features=CrossSiteDocumentBlockingAlways,CrossSiteDocumentBlockingIfIsolating
ソース 。
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.
}
});