diff options
author | Masahiro FUJIMOTO <mfujimot@gmail.com> | 2021-09-24 01:43:08 +0900 |
---|---|---|
committer | Masahiro FUJIMOTO <mfujimot@gmail.com> | 2021-10-02 11:48:06 +0900 |
commit | 66e54c5f2833d73bb35fd6aede54902440e0b50c (patch) | |
tree | b62ef19ad28c19557cde464fbe06d1b28f174534 | |
parent | 0d4eb6823d60b7b48bcfd972d10e1032af60307e (diff) | |
download | translated-content-66e54c5f2833d73bb35fd6aede54902440e0b50c.tar.gz translated-content-66e54c5f2833d73bb35fd6aede54902440e0b50c.tar.bz2 translated-content-66e54c5f2833d73bb35fd6aede54902440e0b50c.zip |
Web/HTTP/CORS を更新
- Markdown 化
- 2021/09/06 時点の英語版に同期
-rw-r--r-- | files/ja/web/http/cors/cors_principle.png | bin | 0 -> 20192 bytes | |||
-rw-r--r-- | files/ja/web/http/cors/cred-req-updated.png | bin | 0 -> 8649 bytes | |||
-rw-r--r-- | files/ja/web/http/cors/index.md | 541 | ||||
-rw-r--r-- | files/ja/web/http/cors/preflight_correct.png | bin | 0 -> 24349 bytes | |||
-rw-r--r-- | files/ja/web/http/cors/simple-req-updated.png | bin | 0 -> 5933 bytes |
5 files changed, 271 insertions, 270 deletions
diff --git a/files/ja/web/http/cors/cors_principle.png b/files/ja/web/http/cors/cors_principle.png Binary files differnew file mode 100644 index 0000000000..31e6382e11 --- /dev/null +++ b/files/ja/web/http/cors/cors_principle.png diff --git a/files/ja/web/http/cors/cred-req-updated.png b/files/ja/web/http/cors/cred-req-updated.png Binary files differnew file mode 100644 index 0000000000..87834b5356 --- /dev/null +++ b/files/ja/web/http/cors/cred-req-updated.png diff --git a/files/ja/web/http/cors/index.md b/files/ja/web/http/cors/index.md index 234fb204f7..eed67059f9 100644 --- a/files/ja/web/http/cors/index.md +++ b/files/ja/web/http/cors/index.md @@ -4,190 +4,182 @@ slug: Web/HTTP/CORS tags: - AJAX - CORS + - オリジン間リソース共有 - Fetch - Fetch API - HTTP - HTTP アクセス制御 - - Security + - 同一オリジンポリシー + - セキュリティ - XMLHttpRequest - l10n:priority - - オリジン間リソース共有 - - セキュリティ - - 同一オリジンポリシー translation_of: Web/HTTP/CORS --- -<div>{{HTTPSidebar}}</div> +{{HTTPSidebar}} + +オリジン間リソース共有 (Cross-Origin Resource Sharing, {{Glossary("CORS")}}) は、追加の {{Glossary("HTTP")}} ヘッダーを使用して、ある{{glossary("origin", "オリジン")}}で動作しているウェブアプリケーションに、異なるオリジンにある選択されたリソースへのアクセス権を与えるようブラウザーに指示するための仕組みです。ウェブアプリケーションは、自分とは異なるオリジン (ドメイン、プロトコル、ポート番号) にあるリソースをリクエストするとき、オリジン間 HTTP リクエストを実行します。 + +オリジン間リクエストとは、例えば `https://domain-a.com` で提供されているウェブアプリケーションのフロントエンド JavaScript コードが {{domxref("XMLHttpRequest")}} を使用して `https://domain-b.com/data.json` へリクエストを行うような場合です。 -<p><span class="seoSummary"><ruby><strong>オリジン間リソース共有</strong><rp> (</rp><rt>Cross-Origin Resource Sharing</rt><rp>) </rp></ruby> ({{Glossary("CORS")}}) は、追加の {{Glossary("HTTP")}} ヘッダーを使用して、ある{{glossary("origin", "オリジン")}}で動作しているウェブアプリケーションに、異なるオリジンにある選択されたリソースへのアクセス権を与えるようブラウザーに指示するための仕組みです。</span>ウェブアプリケーションは、自分とは異なるオリジン (ドメイン、プロトコル、ポート番号) にあるリソースをリクエストするとき、オリジン間 HTTP リクエストを実行します。</p> +セキュリティ上の理由から、ブラウザーは、スクリプトによって開始されるオリジン間 HTTP リクエストを制限しています。例えば、 `XMLHttpRequest`や [Fetch API](/en-US/docs/Web/API/Fetch_API) は[同一オリジンポリシー](/en-US/docs/Web/Security/Same-origin_policy) (same-origin policy) に従います。つまり、これらの API を使用するウェブアプリケーションは、そのアプリケーションが読み込まれたのと同じオリジンに対してのみリソースのリクエストを行うことができ、それ以外のオリジンからの場合は正しい CORS ヘッダーを含んでいることが必要です。 -<p>オリジン間リクエストの一例: <code>https://domain-a.com</code> で提供されているウェブアプリケーションのフロントエンド JavaScript コードが {{domxref("XMLHttpRequest")}} を使用して <code>https://domain-b.com/data.json</code> へリクエストを行う場合。</p> +![](cors_principle.png) -<p>セキュリティ上の理由から、ブラウザーは、スクリプトによって開始されるオリジン間 HTTP リクエストを制限しています。例えば、 <code>XMLHttpRequest</code>や <a href="/ja/docs/Web/API/Fetch_API">Fetch API</a> は<ruby><a href="/ja/docs/Web/Security/Same-origin_policy">同一オリジンポリシー</a><rp> (</rp><rt>same-origin policy</rt><rp>) </rp></ruby>に従います。つまり、これらの API を使用するウェブアプリケーションは、そのアプリケーションが読み込まれたのと同じオリジンに対してのみリソースのリクエストを行うことができ、それ以外のオリジンの場合は正しい CORS ヘッダーを含んでいることが必要です。</p> +CORS の仕組みは、安全なオリジン間のリクエストとブラウザー・サーバー間のデータ転送を支援します。最近のブラウザーは CORS を `XMLHttpRequest` や [Fetch](/en-US/docs/Web/API/Fetch_API) などの API で使用して、オリジン間 HTTP リクエストのリスクの緩和に役立てています。 -<p><img alt="" src="cors_principle.png"></p> +## この記事を読むべき人 -<p>CORS の仕組みは、安全なオリジン間のリクエストとブラウザー・サーバー間のデータ転送を支援します。最近のブラウザーは CORS を <code>XMLHttpRequest</code> や <a href="/ja/docs/Web/API/Fetch_API">Fetch</a> などの API で使用して、オリジン間 HTTP リクエストのリスクの緩和に役立てています。</p> +誰もが読むべきです。 -<h2 id="Who_should_read_this_article" name="Who_should_read_this_article">この記事を読むべき人</h2> +もっと具体的に言えば、この記事は**ウェブ管理者**、**サーバー開発者**、**フロントエンド開発者**向けです。最近のブラウザーはヘッダーやポリシーの強制を含む、オリジン間共有のクライアント側コンポーネントを扱います。しかし CORS 標準は、サーバーが新たなリクエストヘッダーやレスポンスヘッダーを扱わなければならないことを示しています。 -<p>誰もが読むべきです。</p> +## CORS を使用したリクエストとは -<p>もっと具体的に言えば、この記事は<strong>ウェブ管理者</strong>、<strong>サーバー開発者</strong>、<strong>フロントエンド開発者</strong>向けです。最近のブラウザーはヘッダーやポリシーの強制を含む、オリジン間共有のクライアント側コンポーネントを扱います。しかし CORS 標準は、サーバーが新たなリクエストヘッダーやレスポンスヘッダーを扱わなければならないことを示しています。サーバー開発者向けには、<a href="/ja/docs/Web/HTTP/CORS">サーバーの観点によるオリジン間共有 (PHP コードスニペット付き)</a> についての議論を合わせてお読みください。</p> +この [cross-origin sharing standard](https://fetch.spec.whatwg.org/#http-cors-protocol) では、以下についてサイト間の HTTP リクエストができるようにしています。 -<h2 id="What_requests_use_CORS" name="What_requests_use_CORS">CORS を使用したリクエストとは</h2> +- 前述のような {{domxref("XMLHttpRequest")}} または [Fetch API](/en-US/docs/Web/API/Fetch_API) の呼び出し。 +- ウェブフォント (CSS の `@font-face` で別ドメインのフォントを利用するため)。[これによりサーバーは、許可したウェブサイトのみから読み込みんで利用できる TrueType フォントを提供することができます。](https://www.w3.org/TR/css-fonts-3/#font-fetching-requirements) +- [WebGL テクスチャ](/en-US/docs/Web/API/WebGL_API/Tutorial/Using_textures_in_WebGL)。 +- [画像から生成した CSS シェイプ](/en-US/docs/Web/CSS/CSS_Shapes/Shapes_From_Images)。 -<p>この<a class="external" href="https://fetch.spec.whatwg.org/#http-cors-protocol">オリジン間共有仕様</a>は、以下のようなサイト間 HTTP リクエストを有効にすることができます。</p> +この記事では、 HTTP ヘッダーの要件を含むオリジン間リソース共有の全般的な説明を行います。 -<ul> - <li>前述のように {{domxref("XMLHttpRequest")}} または <a href="/ja/docs/Web/API/Fetch_API">Fetch API</a> を呼び出す。</li> - <li>ウェブフォント (CSS の <code>@font-face</code> で別ドメインのフォントを利用するため)。<a class="external" href="https://www.w3.org/TR/css-fonts-3/#font-fetching-requirements">これによりサーバーは、許可したウェブサイトのみから読み込みや利用ができる TrueType フォントを提供できます</a>。</li> - <li><a href="/ja/docs/Web/API/WebGL_API/Tutorial/Using_textures_in_WebGL">WebGL テクスチャ</a>。</li> - <li>{{domxref("CanvasRenderingContext2D.drawImage()", "drawImage()")}} を使用してキャンバスに描画される画像やビデオフレーム。</li> - <li><a href="/ja/docs/Web/CSS/CSS_Shapes/Shapes_From_Images">画像から生成する CSS シェイプ</a>。</li> -</ul> +## 機能概要 -<p>この記事では、オリジン間リソース共有の全般的な説明と併せて、 HTTP ヘッダーの要件についても説明します。</p> +オリジン間リソース共有の仕様は、ウェブブラウザーから情報を読み取ることを許可されているオリジンをサーバーが記述することができる、新たな [HTTP ヘッダー](/en-US/docs/Web/HTTP/Headers)を追加することで作用します。加えて仕様書では、サーバーの情報に副作用を引き起こすことがある HTTP のリクエストメソッド (特に {{HTTPMethod("GET")}} 以外の HTTP メソッドや、特定の [MIME タイプ](/en-US/docs/Web/HTTP/Basics_of_HTTP/MIME_types)を伴う {{HTTPMethod("POST")}}) のために、ブラウザーが HTTP の {{HTTPMethod("OPTIONS")}} リクエストメソッドを用いて、あらかじめリクエストの「プリフライト」 (サーバーから対応するメソッドの一覧を収集すること) を行い、サーバーの「認可」のもとに実際のリクエストを送信することを指示しています。サーバーはリクエスト時に「資格情報」 ([Cookie](/en-US/docs/Web/HTTP/Cookies) や [HTTP 認証](/en-US/docs/Web/HTTP/Authentication)など) を送信するべきかをクライアントに伝えることもできます。 -<h2 id="Functional_overview" name="Functional_overview">機能概要</h2> +CORS は様々なエラーで失敗することがありますが、セキュリティ上の理由から、エラーについて *JavaScript から知ることができない*よう定められています。コードからはエラーが発生したということしか分かりません。何が悪かったのかを具体的に知ることができる唯一の方法は、ブラウザーのコンソールで詳細を見ることです。 -<p>オリジン間リソース共有の仕様は、ウェブブラウザーから情報を読み取ることを許可されているオリジンをサーバーが記述することができる、新たな <a href="/ja/docs/Web/HTTP/Headers">HTTP ヘッダー</a>を追加することで作用します。加えて仕様書では、サーバーの情報に副作用を引き起こすことがある HTTP のリクエストメソッド (特に {{HTTPMethod("GET")}} 以外の HTTP メソッドや、特定の <a href="/ja/docs/Web/HTTP/Basics_of_HTTP/MIME_types">MIME タイプ</a>を伴う {{HTTPMethod("POST")}}) のために、ブラウザーが HTTP の {{HTTPMethod("OPTIONS")}} リクエストメソッドを用いて、あらかじめリクエストの「プリフライト」 (サーバーから対応するメソッドの一覧を収集すること) を行い、サーバーの「認可」のもとに実際のリクエストを送信することを指示しています。サーバーはリクエスト時に「資格情報」 (<a href="/ja/docs/Web/HTTP/Cookies">Cookie</a> や <a href="/ja/docs/Web/HTTP/Authentication">HTTP 認証</a> など) を送信するべきかをクライアントに伝えることもできます。</p> +以降の節ではシナリオの説明に加え、 HTTP ヘッダーの使い方の詳細も提供します。 -<p>CORS は様々なエラーで失敗することがありますが、セキュリティ上の理由から、エラーについて <em>JavaScript から知ることができない</em>よう定められています。コードからはエラーが発生したということしか分かりません。何が悪かったのかを具体的に知ることができる唯一の方法は、ブラウザーのコンソールで詳細を見ることです。</p> +## アクセス制御シナリオの例 -<p>以降の節ではシナリオの説明に加え、 HTTP ヘッダーの使い方の詳細も提供します。</p> +オリジン間リソース共有の動作の仕組みを説明する 3 つのシナリオを示します。これらの例はすべて {{domxref("XMLHttpRequest")}} を用いており、対応しているブラウザーにおいて、サイトをまたいでアクセスすることができます。 -<h2 id="Examples_of_access_control_scenarios" name="Examples_of_access_control_scenarios">アクセス制御シナリオの例</h2> +### 単純リクエスト -<p>オリジン間リソース共有がどのように動作するかを説明する3つのシナリオを示します。これらの例はすべて {{domxref("XMLHttpRequest")}} を用いており、対応しているブラウザーにおいて、サイトをまたいでアクセスすることができます。</p> +リクエストによっては {{Glossary("Preflight_request","CORS プリフライト")}}を発生させません。これをこの記事では*単純リクエスト*と呼んでいますが、 (CORS を定義している) {{SpecName("Fetch")}} 仕様書ではこの用語を使用していません。*単純リクエスト*は、**以下のすべての条件を満たす**ものです。 -<p>サーバー側から見たオリジン間リソース共有の説明 (PHP のコードスニペットを含む) は <a class="internal" href="/ja/docs/Web/HTTP/CORS">Server-Side Access Control (CORS)</a> の記事にあります。</p> +- 許可されているメソッドのうちのいずれかであること。 -<h3 id="Simple_requests" name="Simple_requests">単純リクエスト</h3> + - {{HTTPMethod("GET")}} + - {{HTTPMethod("HEAD")}} + - {{HTTPMethod("POST")}} -<p>リクエストによっては <a href="#preflighted_requests">CORS プリフライト</a>を引き起こさないものがあります。これをこの記事では<em>「単純リクエスト」</em>と呼んでいますが、 (CORS を定義している) {{SpecName('Fetch')}} 仕様書ではこの用語を使用していません。 「単純リクエスト」は、<strong>以下のすべての条件を満たす</strong>ものです。</p> +- ユーザーエージェントによって自動的に設定されたヘッダー (たとえば {{HTTPHeader("Connection")}}、 {{HTTPHeader("User-Agent")}}、 または [Fetch 仕様書で*禁止ヘッダー名*として定義されているヘッダー](https://fetch.spec.whatwg.org/#forbidden-header-name))を除いて、手動で設定できるヘッダーは、 [Fetch 仕様書で CORS セーフリストリクエストヘッダーとして定義されている](https://fetch.spec.whatwg.org/#cors-safelisted-request-header)</a>以下のヘッダーだけです。 -<ul> - <li>許可されているメソッドのうちの一つであること。 - <ul> - <li>{{HTTPMethod("GET")}}</li> - <li>{{HTTPMethod("HEAD")}}</li> - <li>{{HTTPMethod("POST")}}</li> - </ul> - </li> - <li>ユーザーエージェントによって自動的に設定されたヘッダー (たとえば {{HTTPHeader("Connection")}}、 {{HTTPHeader("User-Agent")}}、 または <a href="https://fetch.spec.whatwg.org/#forbidden-header-name">Fetch 仕様書で「禁止ヘッダー名」として定義されているヘッダー</a>) を除いて、手動で設定できるヘッダーは、 <a href="https://fetch.spec.whatwg.org/#cors-safelisted-request-header">Fetch 仕様書で「CORS セーフリストリクエストヘッダー」として定義されている</a>以下のヘッダーだけです。 - <ul> - <li>{{HTTPHeader("Accept")}}</li> - <li>{{HTTPHeader("Accept-Language")}}</li> - <li>{{HTTPHeader("Content-Language")}}</li> - <li>{{HTTPHeader("Content-Type")}} (但し、下記の要件を満たすもの)</li> - </ul> - </li> - <li>{{HTTPHeader("Content-Type")}} ヘッダーでは以下の値のみが許可されています。 - <ul> - <li><code>application/x-www-form-urlencoded</code></li> - <li><code>multipart/form-data</code></li> - <li><code>text/plain</code></li> - </ul> - </li> - <li>リクエストに使用されるどの {{domxref("XMLHttpRequestUpload")}} にもイベントリスナーが登録されていないこと。これらは正しく {{domxref("XMLHttpRequest.upload")}} を使用してアクセスされます。</li> - <li>リクエストに {{domxref("ReadableStream")}} オブジェクトが使用されていないこと。</li> -</ul> + - {{HTTPHeader("Accept")}} + - {{HTTPHeader("Accept-Language")}} + - {{HTTPHeader("Content-Language")}} + - {{HTTPHeader("Content-Type")}} (但し、下記の要件を満たすもの) -<div class="note"><strong>注:</strong> これらはウェブコンテンツが発行可能になっているサイト間リクエストと同じ種類のものであり、サーバーが適切なヘッダーを送信しなければレスポンスデータは送信元へ送られません。従ってクロスサイトリクエストフォージェリ対策をしているサイトは、 HTTP アクセス制限について新たに心配することはありません。</div> +- {{HTTPHeader("Content-Type")}} ヘッダーでは以下の値のみが許可されています。 -<div class="note"> -<p><strong>注:</strong> WebKit Nightly および Safari Technology Preview は、 {{HTTPHeader("Accept")}}, {{HTTPHeader("Accept-Language")}}, {{HTTPHeader("Content-Language")}} ヘッダーの値に追加の制限を掛けています。これらのヘッダーが「標準外」の値の場合、 WebKit/Safari はそのリクエストが「単純リクエスト」の条件に合うとは判断しません。 WebKit/Safari がこれらのヘッダーのどの値を「標準外」と判断するかについては、以下の WebKit のバグを除いて文書化されていません。</p> + - `application/x-www-form-urlencoded` + - `multipart/form-data` + - `text/plain` -<ul> - <li><a href="https://bugs.webkit.org/show_bug.cgi?id=165178" rel="nofollow noreferrer">Require preflight for non-standard CORS-safelisted request headers Accept, Accept-Language, and Content-Language</a></li> - <li><a href="https://bugs.webkit.org/show_bug.cgi?id=165566" rel="nofollow noreferrer">Allow commas in Accept, Accept-Language, and Content-Language request headers for simple CORS</a></li> - <li><a href="https://bugs.webkit.org/show_bug.cgi?id=166363" rel="nofollow noreferrer">Switch to a blacklist model for restricted Accept headers in simple CORS requests</a></li> -</ul> +- {{domxref("XMLHttpRequest")}} オブジェクトを使用してリクエストを行う場合は、 {{domxref("XMLHttpRequest.upload")}} プロパティから返されるオブジェクトにイベントリスナーが登録されていないこと。すなわち、 {{domxref("XMLHttpRequest")}} インスタンスを `xhr` とした場合、どのコードも `xhr.upload.addEventListener()` が呼び出してアップロードを監視するためのイベントリスナーを追加していないこと。 +- リクエストに {{domxref("ReadableStream")}} オブジェクトが使用されていないこと。 -<p>これは仕様の一部ではないので、他のブラウザーはこの追加の制限を実装していません。</p> -</div> +> **Note:** WebKit Nightly および Safari Technology Preview は、 {{HTTPHeader("Accept")}}、{{HTTPHeader("Accept-Language")}}、{{HTTPHeader("Content-Language")}} ヘッダーの値に追加の制限を掛けています。これらのヘッダーが「標準外」の値の場合、 WebKit/Safari はそのリクエストが「単純リクエスト」の条件に合うとは判断しません。 WebKit/Safari がこれらのヘッダーのどの値を「標準外」と判断するかについては、以下の WebKit のバグを除いて文書化されていません。 +> +> - [Require preflight for non-standard CORS-safelisted request headers Accept, Accept-Language, and Content-Language](https://bugs.webkit.org/show_bug.cgi?id=165178) +> - [Allow commas in Accept, Accept-Language, and Content-Language request headers for simple CORS](https://bugs.webkit.org/show_bug.cgi?id=165566) +> - [Switch to a blacklist model for restricted Accept headers in simple CORS requests](https://bugs.webkit.org/show_bug.cgi?id=166363) +> +> これは仕様の一部ではないので、他のブラウザーはこの追加の制限を実装していません。 -<p>例えば、ドメイン <code class="plain">https://foo.example</code> にあるウェブコンテンツがドメイン <code class="plain">https://bar.other</code> にあるコンテンツを呼び出したいと仮定します。以下のようなコードが <code>foo.example</code> 内の JavaScript で使用されるかもしれません。</p> +例えば、ドメイン `https://foo.example` にあるウェブコンテンツがドメイン `https://bar.other` にあるコンテンツを呼び出したいとします。以下のようなコードが `foo.example` 内の JavaScript で使用されるかもしれません。 -<pre class="brush: js notranslate" id="line1">const xhr = new XMLHttpRequest(); +```js +const xhr = new XMLHttpRequest(); const url = 'https://bar.other/resources/public-data/'; xhr.open('GET', url); xhr.onreadystatechange = someHandler; xhr.send(); -</pre> +``` -<p>これは、特権を扱うために CORS ヘッダーを使用して、クライアントとサーバーの間で簡単なデータ交換を行います。</p> +これは、特権を扱うために CORS ヘッダーを使用して、クライアントとサーバーの間で簡単なデータ交換を行います。 -<p><img alt="" src="simple-req-updated.png"></p> +![](simple-req-updated.png) -<p>この場合、ブラウザーがサーバーに何を送信し、サーバーが何を返すかを見てみましょう。</p> +この場合、ブラウザーがサーバーに何を送信し、サーバーが何を返すかを見てみましょう。 -<pre class="brush: shell notranslate">GET /resources/public-data/ HTTP/1.1 +``` +GET /resources/public-data/ HTTP/1.1 Host: bar.other User-Agent: Mozilla/5.0 (Macintosh; Intel Mac OS X 10.14; rv:71.0) Gecko/20100101 Firefox/71.0 Accept: text/html,application/xhtml+xml,application/xml;q=0.9,*/*;q=0.8 Accept-Language: en-us,en;q=0.5 Accept-Encoding: gzip,deflate Connection: keep-alive -<strong>Origin: https://foo.example</strong> -</pre> +Origin: https://foo.example +``` -<p>特筆すべきリクエストヘッダーは {{HTTPHeader("Origin")}} であり、呼び出しが <code class="plain">https://foo.example</code> から来たことを表します。</p> +特筆すべきリクエストヘッダーは {{HTTPHeader("Origin")}} であり、呼び出しが `https://foo.example` から来たことを表します。 -<pre class="notranslate">HTTP/1.1 200 OK +``` +HTTP/1.1 200 OK Date: Mon, 01 Dec 2008 00:23:53 GMT Server: Apache/2 -<strong>Access-Control-Allow-Origin: *</strong> +Access-Control-Allow-Origin: * Keep-Alive: timeout=2, max=100 Connection: Keep-Alive Transfer-Encoding: chunked Content-Type: application/xml -[…XML データ…]</pre> +[…XML データ…] +``` + +レスポンスでは、サーバーが {{HTTPHeader("Access-Control-Allow-Origin")}} ヘッダーを `Access-Control-Allow-Origin: *` と送り返しており、そのリソースが**すべての**ドメインからアクセスできることを示しています。 + +``` +Access-Control-Allow-Origin: * +``` -<p>レスポンスでは、サーバーが {{HTTPHeader("Access-Control-Allow-Origin")}} ヘッダーを返信しています。 {{HTTPHeader("Origin")}} ヘッダーと {{HTTPHeader("Access-Control-Allow-Origin")}} ヘッダーの使用は、最も単純なアクセス制御プロトコルを表しています。この場合、サーバーは <code>Access-Control-Allow-Origin: *</code> を返しており、これはそのリソースが<strong>すべての</strong>ドメインからアクセスできることを意味します。 <code class="plain">https://bar.other</code> にあるリソースの所有者が、リソースへの制限を <code class="plain">https://foo.example</code> からのリクエスト<em>のみ</em>に制限したいと考えていた場合は、以下のように送信します。</p> +{{HTTPHeader("Origin")}} ヘッダーと {{HTTPHeader("Access-Control-Allow-Origin")}} ヘッダーのこのパターンは、アクセス制御プロトコルのもっとも簡単な使い方です。 `https://bar.other` にあるリソースの所有者が、リソースへの制限を `https://foo.example` からのリクエスト*のみ*に制限したい (すなわち、 `https://foo.examle` 以外のドメインがサイト間の作法でリソースにアクセスを許可しない) と考えていた場合は、以下のように送信します。 -<pre class="notranslate"><code class="plain">Access-Control-Allow-Origin: https://foo.example</code></pre> + Access-Control-Allow-Origin: https://foo.example -<p><code class="plain">https://foo.example</code> 以外のドメインはすべて、サイト間の方法でリソースにアクセスすることがサイト間の方法でリソースにアクセスすることができなくなりました。リソースへのアクセスを許可するには、 <code>Access-Control-Allow-Origin</code> ヘッダーに、リクエストの <code>Origin</code> ヘッダーの中で送信された値を含めてください。</p> +> **Note:** [資格情報を含むリクエスト](#資格情報を含むリクエスト)に応答する場合、サーバーは `Access-Control-Allow-Origin` ヘッダーにオリジンを値として指定する必要があり、"`*`" ワイルドカードを指定することはできません。 -<h3 id="Preflighted_requests" name="Preflighted_requests">プリフライトリクエスト</h3> +<h3 id="Preflighted_requests">プリフライトリクエスト</h3> -<p><a href="#simple_requests">「単純リクエスト」 (前述)</a> とは異なり、「プリフライト」リクエストは始めに {{HTTPMethod("OPTIONS")}} メソッドによる HTTP リクエストを他のドメインにあるリソースに向けて送り、実際のリクエストを送信しても安全かどうかを確かめます。サイト間リクエストがユーザーデータに影響を与える可能性があるような場合に、このようにプリフライトを行います。</p> +[_単純リクエスト_](#単純リクエスト)とは異なり、「プリフライト」リクエストは始めに {{HTTPMethod("OPTIONS")}} メソッドによる HTTP リクエストを他のドメインにあるリソースに向けて送り、実際のリクエストを送信しても安全かどうかを確かめます。サイト間リクエストがユーザーデータに影響を与える可能性があるような場合に、このようにプリフライトを行います。 -<p>以下は、プリフライトが行われるリクエストの例です。</p> +プリフライトが行われるリクエストの例です。 -<pre class="brush: js notranslate" id="line1">const xhr = new XMLHttpRequest(); +```js +const xhr = new XMLHttpRequest(); xhr.open('POST', 'https://bar.other/resources/post-here/'); xhr.setRequestHeader('X-PINGOTHER', 'pingpong'); xhr.setRequestHeader('Content-Type', 'application/xml'); xhr.onreadystatechange = handler; -xhr.send('<person><name>Arun</name></person>'); -</pre> +xhr.send('<person><name>Arun</name></person>'); +``` -<p>上記の例では、 <code>POST</code> で送信する XML の本体を作成しています。また、標準外の <code>X-PINGOTHER</code> HTTP リクエストヘッダーを設定しています。このようなヘッダーは HTTP/1.1 プロトコルに含まれていませんが、ウェブアプリケーションでは一般的に便利なものです。リクエストで <code>Content-Type</code> に <code>application/xml</code> を使用しており、かつカスタムヘッダーを設定しているため、このリクエストではプリフライトを行います。</p> +上記の例では、 `POST` で送信する XML の本体を作成しています。また、標準外の `X-PINGOTHER` HTTP リクエストヘッダーを設定しています。このようなヘッダーは HTTP/1.1 プロトコルに含まれていませんが、ウェブアプリケーションでは一般的に便利なものです。リクエストで `Content-Type` に `application/xml` を使用しており、かつ独自のヘッダーを設定しているため、このリクエストではプリフライトを行います。 -<p><img alt="" src="preflight_correct.png"></p> +![](preflight_correct.png) -<div class="blockIndicator note"> -<p><strong>注</strong>: 後述するように、実際の <code>POST</code> リクエストには <code>Access-Control-Request-*</code> ヘッダーが含まれず、 <code>OPTIONS</code> リクエストのみで必要になります。</p> -</div> +> **Note:** 後述するように、実際の `POST` リクエストでは `Access-Control-Request-*` ヘッダーを含みません。`OPTIONS` リクエストのみで必要になります。 -<p>クライアントとサーバーとの間のやりとりの全容を見てみましょう。最初のやり取りは<em>プリフライトリクエスト/レスポンス</em>です。</p> +クライアントとサーバーとの間のやりとりの全容を見てみましょう。最初のやり取りは*プリフライトリクエスト/レスポンス*です。 -<pre class="brush: shell notranslate">OPTIONS /doc HTTP/1.1 +```plain +OPTIONS /doc HTTP/1.1 Host: bar.other User-Agent: Mozilla/5.0 (Macintosh; Intel Mac OS X 10.14; rv:71.0) Gecko/20100101 Firefox/71.0 Accept: text/html,application/xhtml+xml,application/xml;q=0.9,*/*;q=0.8 Accept-Language: en-us,en;q=0.5 Accept-Encoding: gzip,deflate Connection: keep-alive -Origin: http://foo.example +Origin: https://foo.example Access-Control-Request-Method: POST Access-Control-Request-Headers: X-PINGOTHER, Content-Type - HTTP/1.1 204 No Content Date: Mon, 01 Dec 2008 01:15:39 GMT Server: Apache/2 @@ -198,11 +190,36 @@ Access-Control-Max-Age: 86400 Vary: Accept-Encoding, Origin Keep-Alive: timeout=2, max=100 Connection: Keep-Alive -</pre> +``` -<p>プリフライトリクエストが完了したら、実際のリクエストを送ります。</p> +上記の 1 - 10 行目は {{HTTPMethod("OPTIONS")}} メソッドによるプリフライトリクエストを表します。ブラウザーは上記の JavaScript コードで使用していていたリクエストの引数に基づいて、プリフライトの送信が必要であることを判断します。これによりサーバーは実際のリクエストの引数によって送られるリクエストを受け入れ可能かを応答することができます。 OPTIONS は HTTP/1.1 のメソッドであり、サーバーから付加的な情報を得るために用いるもので、また{{Glossary("Safe/HTTP","安全")}}なメソッド、つまりリソースを変更するためには使用できないメソッドです。 OPTIONS リクエストと合わせて、他にリクエストヘッダーを 2 つ送信していることに注意してください (それぞれ 9 行目と 10 行目です)。 -<pre class="brush: shell notranslate">POST /doc HTTP/1.1 +``` +Access-Control-Request-Method: POST +Access-Control-Request-Headers: X-PINGOTHER, Content-Type +``` + +{{HTTPHeader("Access-Control-Request-Method")}} ヘッダーは、プリフライトリクエストの一部として、実際のリクエストが `POST` リクエストメソッドで送られることをサーバーに通知します。 {{HTTPHeader("Access-Control-Request-Headers")}} ヘッダーは、実際のリクエストにカスタムヘッダーである `X-PINGOTHER` および Content-Type が含まれることをサーバーに通知します。ここでサーバーは、この状況下でリクエストの受け入れを望むかを判断する機会が与えられます。 + +上記の 13 - 22 行目はサーバーが返すレスポンスであり、リクエストメソッド (`POST`) とリクエストヘッダー (`X-PINGOTHER`) が受け入れられることを示しています。特に、 16 - 19 行目を見てみましょう。 + +``` +Access-Control-Allow-Origin: https://foo.example +Access-Control-Allow-Methods: POST, GET, OPTIONS +Access-Control-Allow-Headers: X-PINGOTHER, Content-Type +Access-Control-Max-Age: 86400 +``` + +サーバーは `Access-Control-Allow-Origin: https://foo.example` により、アクセスをリクエストしているオリジンのドメインだけに限定することを返答しています。また、 `Access-Control-Allow-Methods` を返しており、これは当該リソースへの問い合わせで `POST` および `GET` が実行可能なメソッドであることを伝えます。なお、このヘッダーはレスポンスヘッダーの {{HTTPHeader("Allow")}} と似ていますが、アクセス制御でのみ使用されることに注意してください。 + +またサーバーは、 `Access-Control-Allow-Headers` を "`X-PINGOTHER, Content-Type`" の値で送信し、実際のリクエストで使用されるヘッダーを承認しています。 `Access-Control-Allow-Methods` と同様に、 `Access-Control-Allow-Headers` は受け入れ可能なヘッダーをカンマ区切りのリストで表します。 + +最後に {{HTTPHeader("Access-Control-Max-Age")}} は、プリフライトリクエストを再び送らなくてもいいように、プリフライトのレスポンスをキャッシュしてよい時間を秒数で与えます。この例では 86400 秒、つまり 24 時間です。なお、ブラウザーはそれぞれ[内部的な上限値](/en-US/docs/Web/HTTP/Headers/Access-Control-Max-Age)を持っており、 `Access-Control-Max-Age` が上回った場合に制限を行います。 + +プリフライトリクエストが完了したら、実際のリクエストを送ります。 + +```plain +POST /doc HTTP/1.1 Host: bar.other User-Agent: Mozilla/5.0 (Macintosh; Intel Mac OS X 10.14; rv:71.0) Gecko/20100101 Firefox/71.0 Accept: text/html,application/xhtml+xml,application/xml;q=0.9,*/*;q=0.8 @@ -217,8 +234,7 @@ Origin: https://foo.example Pragma: no-cache Cache-Control: no-cache -<person><name>Arun</name></person> - +<person><name>Arun</name></person> HTTP/1.1 200 OK Date: Mon, 01 Dec 2008 01:15:40 GMT @@ -232,67 +248,40 @@ Connection: Keep-Alive Content-Type: text/plain [Some XML payload] -</pre> +``` -<p>上記の1-10行目は {{HTTPMethod("OPTIONS")}} メソッドによるプリフライトを表します。ブラウザーは上記で使用された JavaScript コードで使用しているリクエストの引数に基づいて、プリフライトの送信が必要であることを判断します。これによりサーバーは実際のリクエストの引数によって送られるリクエストを受け入れ可能かをレスポンスできます。 OPTIONS はサーバーから付加的な情報を得るために用いる HTTP/1.1 のメソッドであり、また{{Glossary("safe","安全")}}なメソッド、つまりリソースを変更するためには使用できないメソッドです。 OPTIONS リクエストと合わせて、他にリクエストヘッダーを2つ送信していることに注意してください (それぞれ9行目と10行目です)。</p> +#### プリフライトリクエストとリダイレクト -<pre class="brush: none notranslate">Access-Control-Request-Method: POST -Access-Control-Request-Headers: X-PINGOTHER, Content-Type -</pre> +現在のところ、すべてのブラウザーが下記のようなプリフライトリクエストのリダイレクトに対応しているわけではありません。プリフライトリクエストにリダイレクトが発生すると、ブラウザーによっては以下のようなエラーメッセージを報告します。 -<p>{{HTTPHeader("Access-Control-Request-Method")}} ヘッダーは、プリフライトリクエストの一部として、実際のリクエストが <code>POST</code> リクエストメソッドで送られることをサーバーに通知します。 {{HTTPHeader("Access-Control-Request-Headers")}} ヘッダーは、実際のリクエストにカスタムヘッダーである <code>X-PINGOTHER</code> および Content-Type が含まれることをサーバーに通知します。ここでサーバーは、この状況下でリクエストの受け入れを望むかを判断する機会があります。</p> +> The request was redirected to 'https\://example.com/foo', which is disallowed for cross-origin requests that require preflight. +> Request requires preflight, which is disallowed to follow cross-origin redirects. -<p>上記の13-22行目はサーバーが返すレスポンスであり、リクエストメソッド (<code>POST</code>) とリクエストヘッダー (<code>X-PINGOTHER</code>) を受け入れられることを示しています。特に、16-19行目を見てみましょう。</p> +もともと CORS プロトコルはそのような動作を要求していましたが、[その後で必要がないと変更されました](https://github.com/whatwg/fetch/commit/0d9a4db8bc02251cc9e391543bb3c1322fb882f2)。しかし、多くのブラウザーはまだ変更を実装しておらず、もともと要求されていた動作に従っています。 -<pre class="brush: none notranslate">Access-Control-Allow-Origin: http://foo.example -Access-Control-Allow-Methods: POST, GET, OPTIONS -Access-Control-Allow-Headers: X-PINGOTHER, Content-Type -Access-Control-Max-Age: 86400</pre> - -<p>サーバーは <code>Access-Control-Allow-Methods</code> を返しており、これは当該リソースへの問い合わせで <code>POST</code> および <code>GET</code> が実行可能なメソッドであることを伝えます。なお、このヘッダーはレスポンスヘッダーの {{HTTPHeader("Allow")}} と似ていますが、アクセス制御でのみ使用されることに注意してください。</p> - -<p>またサーバーは、 <code>Access-Control-Allow-Headers</code> を <code>X-PINGOTHER</code> の値で送信し、これが実際のリクエストで使用されるヘッダーであることを承認しています。 <code>Access-Control-Allow-Methods</code> と同様に、 <code>Access-Control-Allow-Headers</code> は受け入れ可能なヘッダーをカンマ区切りのリストで表します。</p> - -<p>最後に <code>Access-Control-Max-Age</code> は、プリフライトリクエストを再び送らなくてもいいように、プリフライトのレスポンスをキャッシュしてよい時間を秒数で与えます。この例では86400秒、つまり24時間です。なお、ブラウザーは個々に<a href="/ja/docs/Web/HTTP/Headers/Access-Control-Max-Age">内部の上限値</a>を持っており、 <code>Access-Control-Max-Age</code> が上回った場合に制限を掛けます。</p> - -<h4 id="Preflighted_requests_and_redirects" name="Preflighted_requests_and_redirects">プリフライトリクエストとリダイレクト</h4> - -<p>多くのブラウザーは現在、下記のようなプリフライトリクエストのリダイレクトに対応していません。プリフライトリクエストにリダイレクトが発生すると、多くのブラウザーは以下のようなエラーメッセージを報告します。</p> - -<blockquote> -<p>リクエストがプリフライトを必要とするオリジン間リクエストで許可されていない 'https://example.com/foo' にリダイレクトされました。</p> -</blockquote> - -<blockquote> -<p>リクエストにはプリフライトが必要で、オリジン間のリダイレクトは許可されていません</p> -</blockquote> +ブラウザーが仕様に追いつくまで、以下の一方もしくは両方を行うことでこの制限を回避することができます。 -<p>もともと CORS プロトコルはそのような振る舞いを要求していましたが、<a href="https://github.com/whatwg/fetch/commit/0d9a4db8bc02251cc9e391543bb3c1322fb882f2">その後で必要がないと変更されました</a>。しかし、多くのブラウザーはまだ変更を実装しておらず、もともと要求されていた振る舞いに従っています。</p> +- サーバー側の振る舞いを変更して、プリフライトが発生しないようにするか、リダイレクトが発生しないようにする +- リクエストをプリフライトを起こさない[単純リクエスト](#単純リクエスト)などに変更する -<p>ブラウザーが仕様に追いつくまで、以下の一方もしくは両方を行うことでこの制限を回避することができます。</p> +これらの変更ができない場合は、次のような別な方法があります。 -<ul> - <li>サーバー側の振る舞いを変更して、プリフライトが発生しないようにするか、リダイレクトが発生しないようにする</li> - <li>リクエストをプリフライトを起こさない<a href="#simple_requests">単純リクエスト</a>などに変更する</li> -</ul> +1. [単純リクエスト](#単純リクエスト)を行い (Fetch API の {{domxref("Response.url")}} または {{domxref("XMLHttpRequest.responseURL")}} を使用する)、実際のプリフライトリクエストが転送される先を特定する。 +2. 最初のステップの `Response.url` または `XMLHttpRequest.responseURL` で得た URL を使用して、もう一つのリクエスト (*本当の*リクエスト) を行う。 -<p>これらの変更ができない場合は、次のような別な方法があります。</p> +ただし、リクエストに `Authorization` ヘッダーが存在するためにプリフライトが発生するリクエストの場合、上記の手順を使用して制限を回避することはできません。リクエストが行われているサーバーを制御できない限り、まったく回避することはできません。 -<ol> - <li><a href="#simple_requests">単純リクエスト</a>を行い (Fetch API の {{domxref("Response.url")}} または {{domxref("XMLHttpRequest.responseURL")}} を使用して)、実際のプリフライトリクエストが転送される先を特定する。</li> - <li>最初のステップの <code>Response.url</code> または <code>XMLHttpRequest.responseURL</code> で得た URL を使用して、もう一つのリクエスト (「本当の」リクエスト) を行う。</li> -</ol> +### 資格情報を含むリクエスト -<p>ただし、リクエストに <code>Authorization</code> ヘッダーが存在するためにプリフライトを引き起こすリクエストの場合、上記の手順を使用して制限を回避することはできません。リクエストが行われているサーバーを制御できない限り、まったく回避することはできません。</p> +> **Note:** 資格情報を含むリクエストを異なるドメインに行う場合、サードパーティクッキーポリシーも適用されます。このポリシーは、この章で説明しているように、サーバーやクライアントでの設定とは無関係に常に実施されます。 -<h3 id="Requests_with_credentials" name="Requests_with_credentials">資格情報を含むリクエスト</h3> +{{domxref("XMLHttpRequest")}} や [Fetch](/en-US/docs/Web/API/Fetch_API) と CORS の両方によって明らかになる最も興味深い機能は、[HTTP クッキー](/en-US/docs/Web/HTTP/Cookies)と HTTP 資格情報によってわかる「資格情報を含む」リクエストを作成することができることです。既定では、サイト間の `XMLHttpRequest` または [Fetch](/en-US/docs/Web/API/Fetch_API) の呼び出しにおいて、ブラウザーは資格情報を送信**しません**。 `XMLHttpRequest` オブジェクトまたは {{domxref("Request")}} のコンストラクターの呼び出し時に、特定のフラグを設定する必要があります。 -<p>{{domxref("XMLHttpRequest")}} や <a href="/ja/docs/Web/API/Fetch_API">Fetch</a> と CORS の両方によって明らかになる最も興味深い機能は、 <a href="/ja/docs/Web/HTTP/Cookies">HTTP クッキー</a>と HTTP 資格情報によってわかる「資格情報を含む」リクエストを作成することができることです。既定では、サイト間の <code>XMLHttpRequest</code> または <a href="/ja/docs/Web/API/Fetch_API">Fetch</a> の呼び出しにおいて、ブラウザーは資格情報を送信<strong>しません</strong>。 <code>XMLHttpRequest</code> オブジェクトまたは {{domxref("Request")}} のコンストラクターの呼び出し時に、特定のフラグを設定する必要があります。</p> +以下の例では `https://foo.example` から読み込まれた元のコンテンツが、 `https://bar.other` にあるリソースに対してクッキーを設定したシンプルな GET リクエストを行います。 foo.example のコンテンツは以下のような JavaScript を含んでいるかもしれません。 -<p>以下の例では <code class="plain">http://foo.example</code> から読み込まれた元のコンテンツが、 <code class="plain">http://bar.other</code> にあるリソースに対してクッキーを設定したシンプルな GET リクエストを行います。 foo.example のコンテンツは以下のような JavaScript を含んでいるかもしれません。</p> - -<pre class="brush: js notranslate" id="line1">const invocation = new XMLHttpRequest(); -const url = 'http://bar.other/resources/credentialed-content/'; +```js +const invocation = new XMLHttpRequest(); +const url = 'https://bar.other/resources/credentialed-content/'; function callOtherDomain() { if (invocation) { @@ -301,26 +290,27 @@ function callOtherDomain() { invocation.onreadystatechange = handler; invocation.send(); } -}</pre> +} +``` -<p>7行目で、クッキー付きで呼び出しを行うために {{domxref("XMLHttpRequest")}} に設定する必要があるフラグ、 <code>withCredentials</code> という真偽値型の値を示しています。既定では、クッキーなしで呼び出しが行われます。これは単純な <code>GET</code> リクエストなのでプリフライトは行いませんが、ブラウザーは {{HTTPHeader("Access-Control-Allow-Credentials")}}<code>: true</code> ヘッダーを持たないレスポンスを<strong>拒否</strong>し、ウェブコンテンツを呼び出すレスポンスを作成<strong>しない</strong>でしょう。</p> +7 行目で、クッキー付きで呼び出しを行うために {{domxref("XMLHttpRequest")}} に設定する必要があるフラグ、 `withCredentials` という論理型の値を示しています。既定では、クッキーなしで呼び出しが行われます。これは単純な `GET` リクエストなのでプリフライトは行いませんが、ブラウザーは {{HTTPHeader("Access-Control-Allow-Credentials")}}`: true` ヘッダーを持たないレスポンスを**拒否**し、ウェブコンテンツを呼び出すレスポンスを作成**しない**でしょう。 -<p><img alt="" src="cred-req-updated.png"></p> +![](cred-req-updated.png) -<p>以下はクライアントとサーバーとの間のやりとりの例です。</p> +以下はクライアントとサーバーとの間のやりとりの例です。 -<pre class="brush: shell notranslate">GET /resources/credentialed-content/ HTTP/1.1 +```plain +GET /resources/credentialed-content/ HTTP/1.1 Host: bar.other User-Agent: Mozilla/5.0 (Macintosh; Intel Mac OS X 10.14; rv:71.0) Gecko/20100101 Firefox/71.0 Accept: text/html,application/xhtml+xml,application/xml;q=0.9,*/*;q=0.8 Accept-Language: en-us,en;q=0.5 Accept-Encoding: gzip,deflate Connection: keep-alive -Referer: http://foo.example/examples/credential.html -Origin: http://foo.example +Referer: https://foo.example/examples/credential.html +Origin: https://foo.example Cookie: pageAccess=2 - HTTP/1.1 200 OK Date: Mon, 01 Dec 2008 01:34:52 GMT Server: Apache/2 @@ -336,167 +326,178 @@ Keep-Alive: timeout=2, max=100 Connection: Keep-Alive Content-Type: text/plain - [text/plain payload] -</pre> +``` + +10 行目に `https://bar.other` 向けのクッキーが含まれていますが、bar.other が {{HTTPHeader("Access-Control-Allow-Credentials")}}`: true` (17 行目) をレスポンスに含めなければ、レスポンスは無視されウェブコンテンツで使用できません。 + +#### プリフライトリクエストと資格情報 + +CORS のプリフライトリクエストに資格情報を含めてはいけません。プリフライトリスクエストへの*レスポンス*には `Access-Control-Allow-Credentials: true` を指定して、実際のリクエストを資格情報付きで行うことができることを示す必要があります。 -<p>10行目に <code class="plain">http://bar.other</code> 向けのクッキーが含まれていますが、bar.other が {{HTTPHeader("Access-Control-Allow-Credentials")}}<code>: true</code> (17行目) をレスポンスに含めなければ、レスポンスは無視されウェブコンテンツで使用できません。</p> +> **Note:** エンタープライズ認証サービスの中には、 {{SpecName("Fetch","#cors-protocol-and-credentials")}} 仕様書に反して、プリフライトリクエストで TLS クライアント証明書を送信することを要求するものがあります。 +> +> Firefox 87 では、`network.cors_preflight.allow_client_cert` を `true` に設定することで、この準拠していない動作を有効にすることができます。({{bug(1511151)}}). Chromium ベースのブラウザーでは現在、CORS プリフライトリクエストで TLS クライアント証明書を常に送信します ([Chrome bug 775438](https://bugs.chromium.org/p/chromium/issues/detail?id=775438))。 -<h4 id="Credentialed_requests_and_wildcards" name="Credentialed_requests_and_wildcards">資格情報付きリクエストとワイルドカード</h4> +#### 資格情報付きリクエストとワイルドカード -<p>資格情報を含むリクエストに対するレスポンスの時、サーバーは <code>Access-Control-Allow-Origin</code> ヘッダーで "<code>*</code>" ワイルドカードではなくオリジンを指定<strong>しなければなりません</strong>。</p> +資格情報付きリクエストに返答する場合、 -<p>上記の例のリクエストヘッダーは <code>Cookie</code> ヘッダーを含んでいるため、 <code>Access-Control-Allow-Origin</code> ヘッダーが "*" であったらリクエストは失敗します。 <code>Access-Control-Allow-Origin</code> ヘッダーの値が "<code>*</code>" ワイルドカードではなく "<code class="plain">http://foo.example</code>" (実際のオリジン) なので、ウェブコンテンツの呼び出しに対して資格情報を意識したコンテンツが返ります。</p> +- サーバーは `Access-Control-Allow-Origin` ヘッダーで "`*`" ワイルドカードを指定**してはならず**、 `Access-Control-Allow-Origin: https://example.com` のように、明示的にオリジンを指定しなければなりません。 -<p>なお、上記の例の中にある <code>Set-Cookie</code> レスポンスヘッダーは、将来のクッキーの設定も行ないます。失敗した場合、 (使われている API によりますが) 例外が発生します。</p> +- サーバーは `Access-Control-Allow-Headers` ヘッダーで "`*`" ワイルドカードを指定**してはならず**、 `Access-Control-Allow-Headers: X-PINGOTHER, Content-Type` のように、明示的にヘッダー名を指定しなければなりません。 -<h4 id="Third-party_cookies" name="Third-party_cookies">サードパーティーのクッキー</h4> +- サーバーは `Access-Control-Allow-Methods` ヘッダーで "`*`" ワイルドカードを指定**してはならず**、 `Access-Control-Allow-Methods: POST, GET` のように、明示的にメソッド名を指定しなければなりません。 -<p>CORS のレスポンスに設定されたクッキーは、サードパーティーのクッキーに関する通常のポリシーに従います。上記の例では、ページは <code>foo.example</code> から読み込まれていますが、20行目のクッキーは <code>bar.other</code> から送られているので、ユーザーがブラウザーでサードパーティーのクッキーをすべて拒否するよう設定していた場合は保存されません。</p> +リクエストが資格情報 (多くの場合は `Cookie` ヘッダー) を含んでおり、そのレスポンスが `Access-Control-Allow-Origin: *` ヘッダー (つまりワイルドカード) を含んでいる場合、ブラウザーはレスポンスへのアクセスをブロックし、開発ツールのコンソールに CORS エラーを報告します。 -<h2 id="The_HTTP_response_headers" name="The_HTTP_response_headers">HTTP レスポンスヘッダー</h2> +ただし、リクエストが (`Cookie` ヘッダーのような) 資格情報を含んでおり、そのレスポンスがワイルドカードではない実際のオリジンを含んでいる場合 (例えば `Access-Control-Allow-Origin: https://example.com` など)、ブラウザーは指定されたオリジンからのレスポンスへのアクセスを許可します。 -<p>ここではオリジン間リソース共有の仕様書で定義されている、アクセス制御のためにサーバーが返す HTTP レスポンスヘッダーを掲載します。前の章では、これらの実際の動作の概要を説明しました。</p> +また、レスポンス内の `Access-Control-Allow-Origin` レスポンスヘッダーの値が実際のオリジンではなく "`*`" ワイルドカードであった場合、クッキーは設定されません。 -<h3 id="Access-Control-Allow-Origin">Access-Control-Allow-Origin</h3> +#### サードパーティーのクッキー -<p>返却されるリソースには、以下のような構文で1つの {{HTTPHeader("Access-Control-Allow-Origin")}} ヘッダーがつくことがあります。</p> +CORS のレスポンスに設定されたクッキーは、サードパーティーのクッキーに関する通常のポリシーに従うことに注意してください。上記の例では、ページは `foo.example` から読み込まれていますが、 20 行目のクッキーは `bar.other` から送られているので、ユーザーがブラウザーでサードパーティーのクッキーをすべて拒否するよう設定していた場合は保存されません。 -<pre class="brush: none notranslate">Access-Control-Allow-Origin: <origin> | * -</pre> +リクエスト中のクッキー (10 行目) は、通常のサードパーティクッキーポリシーでも抑制されることがあります。したがって、クッキーポリシーが強制されていると、この章で説明されている機能が無効になり、事実上、認証されたリクエストを行うことができなくなるかもしれません。 -<p><code>Access-Control-Allow-Origin</code> は、リソースへのアクセスを許可するオリジンをブラウザーに伝えるための単一のオリジン、または — 資格情報を<strong>含まない</strong>リクエストにおいては — どのオリジンにもリソースへのアクセスを許可することをブラウザーに伝えるワイルドカード "<code>*</code>" のどちらかを指定することができます。</p> +[SameSite](/en-US/docs/Web/HTTP/Headers/Set-Cookie/SameSite) 属性に関するクッキーポリシーは適用されます。 -<p>例えば、 <code>https://mozilla.org</code> のオリジンからのコードにリソースへのアクセスを許可するには、次のように指定します。</p> +## HTTP レスポンスヘッダー -<pre class="brush: none notranslate">Access-Control-Allow-Origin: https://mozilla.org -Vary: Origin</pre> +この節では、オリジン間リソース共有の仕様書で定義されている、アクセス制御のためにサーバーが返す HTTP レスポンスヘッダーを掲載します。前の章では、これらの実際の動作の概要を説明しました。 -<p>サーバーがワイルドカード "<code>*</code>" ではなく (ホワイトリストの一部としてリクエストするオリジンに基づいて動的に変更される可能性がある) 単一のオリジンを指定した場合は、サーバーは {{HTTPHeader("Vary")}} レスポンスヘッダーに <code>Origin</code> も含めて、サーバーのレスポンスが {{HTTPHeader("Origin")}} リクエストヘッダーの値によって変化することをクライアントに示してください。</p> +### Access-Control-Allow-Origin -<h3 id="Access-Control-Expose-Headers">Access-Control-Expose-Headers</h3> +返却されるリソースには、以下のような構文で 1 つの {{HTTPHeader("Access-Control-Allow-Origin")}} ヘッダーがつくことがあります。 -<p>{{HTTPHeader("Access-Control-Expose-Headers")}} ヘッダーは、ブラウザーがアクセスを許可されるサーバーのホワイトリストにあるヘッダーを示すことができます。</p> +``` +Access-Control-Allow-Origin: <origin> | * +``` -<pre class="brush: none notranslate">Access-Control-Expose-Headers: <header-name>[, <header-name>]* -</pre> +`Access-Control-Allow-Origin` は、リソースへのアクセスを許可するオリジンをブラウザーに伝えるための単一のオリジン、または — 資格情報を**含まない**リクエストにおいては — どのオリジンにもリソースへのアクセスを許可することをブラウザーに伝えるワイルドカード "`*`" のどちらかを指定することができます。 -<p>例えば、以下のようになります。</p> +例えば、 `https://mozilla.org` のオリジンからのコードにリソースへのアクセスを許可するには、次のように指定します。 -<pre class="brush: none notranslate">Access-Control-Expose-Headers: X-My-Custom-Header, X-Another-Custom-Header -</pre> +``` +Access-Control-Allow-Origin: https://mozilla.org +Vary: Origin +``` -<p>これは、ブラウザーに対して <code>X-My-Custom-Header</code> および <code>X-Another-Custom-Header</code> ヘッダーを許可します。</p> +サーバーがワイルドカード "`*`" ではなく (ホワイトリストの一部としてリクエストするオリジンに基づいて動的に変更される可能性がある) 単一のオリジンを指定した場合は、サーバーは `Origin` を {{HTTPHeader("Vary")}} レスポンスヘッダーに含めて、サーバーのレスポンスが {{HTTPHeader("Origin")}} リクエストヘッダーの値によって変化することもクライアントに示してください。 -<h3 id="Access-Control-Max-Age">Access-Control-Max-Age</h3> +### Access-Control-Expose-Headers -<p>このヘッダーはプリフライトリクエストの結果をキャッシュしてよい時間を示します。プリフライトリクエストの例は、前出の例をご覧ください。</p> +{{HTTPHeader("Access-Control-Expose-Headers")}} ヘッダーは、指定されたヘッダーをブラウザー内の JavaScript ({{domxref("XMLHttpRequest.getResponseHeader()","getResponseHeader()")}} など) からアクセスできる許可リストに加えます。 -<pre class="brush: none notranslate">Access-Control-Max-Age: <delta-seconds> -</pre> +``` +Access-Control-Expose-Headers: <header-name>[, <header-name>]* +``` -<p><code>delta-seconds</code> 引数は、結果をキャッシュしてよい時間を秒単位で示します。</p> +例えば、以下のようになります。 -<h3 id="Access-Control-Allow-Credentials">Access-Control-Allow-Credentials</h3> +``` +Access-Control-Expose-Headers: X-My-Custom-Header, X-Another-Custom-Header +``` -<p>{{HTTPHeader("Access-Control-Allow-Credentials")}} は <code>credentials</code> フラグが真であるときに、リクエストへのレスポンスを開示してよいか否かを示します。プリフライトリクエストのレスポンスの一部として用いられたときは、実際のリクエストで資格情報を使用してよいか否かを示します。単純な <code>GET</code> リクエストはプリフライトを行いませんので、リソースへのリクエストが資格情報付きで行われた場合にリソースと共にこのヘッダーを返さなければ、レスポンスはブラウザーによって無視され、ウェブコンテンツに返らないことに注意してください。</p> +これは、ブラウザーに対して `X-My-Custom-Header` および `X-Another-Custom-Header` ヘッダーを許可します。 -<pre class="brush: none notranslate">Access-Control-Allow-Credentials: true -</pre> +### Access-Control-Max-Age -<p><a class="internal" href="#requests_with_credentials">資格情報付きのリクエスト</a>は前に説明したとおりです。</p> +このヘッダーはプリフライトリクエストの結果をキャッシュしてよい時間を示します。プリフライトリクエストの例は、前出の例をご覧ください。 +``` +Access-Control-Max-Age: <delta-seconds> +``` -<h3 id="Access-Control-Allow-Methods">Access-Control-Allow-Methods</h3> +`delta-seconds` 引数は、結果をキャッシュしてよい時間を秒単位で示します。 -<p>{{HTTPHeader("Access-Control-Allow-Methods")}} ヘッダーは、リソースへのアクセス時に許可するメソッドを指定します。これはプリフライトリクエストのレスポンスで用いられます。リクエストのプリフライトを行う条件については前述のとおりです。</p> +### Access-Control-Allow-Credentials -<pre class="brush: none notranslate">Access-Control-Allow-Methods: <method>[, <method>]* -</pre> +{{HTTPHeader("Access-Control-Allow-Credentials")}} は `credentials` フラグが true である場合に、リクエストへのレスポンスを開示してよいか否かを示します。プリフライトリクエストのレスポンスの一部として用いられたときは、実際のリクエストで資格情報を使用してよいか否かを示します。単純な `GET` リクエストはプリフライトを行いませんので、リソースへのリクエストが資格情報付きで行われた場合にリソースと共にこのヘッダーを返さなければ、ブラウザーがそのレスポンスを無視し、ウェブのコンテンツが返されないことに注意してください。 -<p>ブラウザーにこのヘッダーを送信する例を含む、プリフライトリクエストの例は <a class="internal" href="#preflighted_requests">前述のとおりです</a>。</p> +``` +Access-Control-Allow-Credentials: true +``` + +[資格情報付きリクエスト](#資格情報を含むリクエスト)は前に説明したとおりです。 + +### Access-Control-Allow-Methods + +{{HTTPHeader("Access-Control-Allow-Methods")}} ヘッダーは、リソースへのアクセス時に許可するメソッドを指定します。これはプリフライトリクエストのレスポンスで用いられます。リクエストのプリフライトを行う条件については前述のとおりです。 -<h3 id="Access-Control-Allow-Headers">Access-Control-Allow-Headers</h3> +``` +Access-Control-Allow-Methods: <method>[, <method>]* +``` -<p>{{HTTPHeader("Access-Control-Allow-Headers")}} ヘッダーは、実際のリクエストでどの HTTP ヘッダーを使用できるかを示すために、<a class="internal" href="#preflighted_requests">プリフライトリクエスト</a>のレスポンスで使用します。</p> +ブラウザーにこのヘッダーを送信する例を含む、{{Glossary("preflight request", "プリフライトリクエスト")}}の例は前述のとおりです。 -<pre class="brush: none notranslate">Access-Control-Allow-Headers: <header-name>[, <header-name>]* -</pre> +### Access-Control-Allow-Headers -<h2 id="The_HTTP_request_headers" name="The_HTTP_request_headers">HTTP リクエストヘッダー</h2> +{{HTTPHeader("Access-Control-Allow-Headers")}} ヘッダーは{{Glossary("preflight request", "プリフライトリクエスト")}}へのレスポンスで使用され、実際のリクエストを行う際に使用される HTTP ヘッダーを示します。このヘッダーはブラウザーの {{HTTPHeader("Access-Control-Request-Headers")}} ヘッダーに対するサーバー側のレスポンスです。 -<p>この節では、 HTTP リクエストを発行する際、オリジン間リソース共有機能を利用するためにクライアントが使用できるヘッダーの一覧を掲載します。なお、これらのヘッダーはサーバーの呼び出し時に設定されます。サイト間 {{domxref("XMLHttpRequest")}} の機能を使用する開発者は、オリジン間リソース共有のヘッダーをプログラムで設定する必要はありません。</p> +``` +Access-Control-Allow-Headers: <header-name>[, <header-name>]* +``` -<h3 id="Origin">Origin</h3> +## HTTP リクエストヘッダー -<p>{{HTTPHeader("Origin")}} ヘッダーはサイト間のアクセスリクエストやプリフライトリクエストのオリジンを示します。</p> +この節では、 HTTP リクエストを発行する際、オリジン間リソース共有機能を利用するためにクライアントが使用できるヘッダーの一覧を掲載します。なお、これらのヘッダーはサーバーの呼び出し時に設定されます。サイト間 {{domxref("XMLHttpRequest")}} の機能を使用する開発者は、オリジン間リソース共有のリクエストヘッダーをプログラムで設定する必要はありません。 -<pre class="brush: none notranslate">Origin: <origin> -</pre> +### Origin -<p>origin は、リクエストを開始したサーバーを示す URI です。ここにパス情報は含めず、サーバー名だけにします。</p> +{{HTTPHeader("Origin")}} ヘッダーはサイト間のアクセスリクエストやプリフライトリクエストのオリジンを示します。 -<div class="note"><strong>注:</strong> <code>origin</code> の値は <code>null</code> または URI にすることができます。</div> +``` +Origin: <origin> +``` -<p>すべてのアクセス制御リクエストにおいて、 {{HTTPHeader("Origin")}} ヘッダーは<strong>常に</strong>送信されることに注意してください。</p> +origin は、リクエストを開始したサーバーを示す URL です。ここにパス情報は含めず、サーバー名だけにします。 -<h3 id="Access-Control-Request-Method">Access-Control-Request-Method</h3> +> **Note:** `origin` の値は `null` にすることができます。 -<p>{{HTTPHeader("Access-Control-Request-Method")}} はプリフライトリクエストを発信する際に、実際のリクエストを行う際に使用する HTTP メソッドをサーバーに知らせるために使用します。</p> +なお、すべてのアクセス制御リクエストにおいて、 {{HTTPHeader("Origin")}} ヘッダーは**常に**送信されます。 -<pre class="brush: none notranslate">Access-Control-Request-Method: <method> -</pre> +### Access-Control-Request-Method -<p>使用例は<a class="internal" href="#preflighted_requests">前出のとおりです</a>。</p> +{{HTTPHeader("Access-Control-Request-Method")}} はプリフライトリクエストを発信する際に、実際のリクエストを行う際に使用する HTTP メソッドをサーバーに知らせるために使用します。 + +``` +Access-Control-Request-Method: <method> +``` + +使用例は[前述のとおりです。](#preflighted_requests)。 <h3 id="Access-Control-Request-Headers">Access-Control-Request-Headers</h3> -<p>{{HTTPHeader("Access-Control-Request-Headers")}} ヘッダーは、プリフライトリクエストを発信する際に、実際のリクエストを行う際に使用する HTTP ヘッダーをサーバーに知らせるために使用します。</p> - -<pre class="brush: none notranslate">Access-Control-Request-Headers: <field-name>[, <field-name>]* -</pre> - -<p>使用例は <a class="internal" href="#preflighted_requests">前出のとおりです</a>。</p> - -<h2 id="Specifications" name="Specifications">仕様書</h2> - -<table class="standard-table"> - <tbody> - <tr> - <th scope="col">仕様書</th> - <th scope="col">状態</th> - <th scope="col">備考</th> - </tr> - <tr> - <td>{{SpecName('Fetch', '#cors-protocol', 'CORS')}}</td> - <td>{{Spec2('Fetch')}}</td> - <td><a href="https://www.w3.org/TR/cors/">W3C CORS</a> 仕様書を置き換える新しい定義です。</td> - </tr> - </tbody> -</table> - -<h2 id="Browser_compatibility" name="Browser_compatibility">ブラウザーの互換性</h2> - -<p>{{Compat("http.headers.Access-Control-Allow-Origin")}}</p> - -<h3 id="Compatibility_notes" name="Compatibility_notes">互換性のメモ</h3> - -<p>Internet Explorer 8 および 9 は XDomainRequest オブジェクトで CORS を提供していますが、完全な実装は IE 10 で行っています。</p> - -<h2 id="See_also" name="See_also">関連情報</h2> - -<ul> - <li><a href="/ja/docs/Web/HTTP/CORS/Errors">CORS のエラー</a></li> - <li><a href="https://enable-cors.org/server.html">Enable CORS: I want to add CORS support to my server</a></li> - <li>{{domxref("XMLHttpRequest")}}</li> - <li><a href="/ja/docs/Web/API/Fetch_API">Fetch API</a></li> - <li><a href="https://httptoolkit.tech/will-it-cors">Will it CORS?</a> - an interactive CORS explainer & generator</li> - <li><a href="https://www.telerik.com/blogs/using-cors-with-all-modern-browsers">Using CORS with All (Modern) Browsers</a></li> - <li><a href="https://alfilatov.com/posts/run-chrome-without-cors/">How to run Chrome browser without CORS</a></li> - <li><a href="https://stackoverflow.com/questions/43871637/no-access-control-allow-origin-header-is-present-on-the-requested-resource-whe/43881141#43881141">Stack Overflow のよくある問題を解決するための “how to” 情報</a> - <ul> - <li>CORS のプリフライトを防止する方法</li> - <li>CORS プロキシを使用して<em>「Access-Control-Allow-Origin ヘッダーの欠落」</em>を回避する方法</li> - <li><em>「Access-Control-Allow-Origin ヘッダーがワイルドカードを扱えない」</em>ことを修正する方法</li> - </ul> - </li> -</ul> +{{HTTPHeader("Access-Control-Request-Headers")}} ヘッダーは、プリフライトリクエストを発行する際に、実際のリクエストを行う際に ({{domxref("XMLHttpRequest.setRequestHeader()","setRequestHeader()")}} などによって) 使用する HTTP ヘッダーをサーバーに知らせるために使用します。このブラウザー側のヘッダーは、サーバー側のヘッダー {{HTTPHeader("Access-Control-Allow-Headers")}} によって回答されます。 + +``` +Access-Control-Request-Headers: <field-name>[, <field-name>]* +``` + +使用例は[前述のとおりです。](#preflighted_requests)。 + +## 仕様書 + +| 仕様書 | 状態 | 備考 | +| ---------------------------------------------------------------- | ------------------------ | -------------------------------------------------------------------------------- | +| {{SpecName('Fetch', '#cors-protocol', 'CORS')}} | {{Spec2('Fetch')}} | [W3C CORS](https://www.w3.org/TR/cors/) 仕様書に代わる新しい定義です。 | + +## ブラウザーの互換性 + +{{Compat("http.headers.Access-Control-Allow-Origin")}} + +## 関連情報 + +- [CORS のエラー](/en-US/docs/Web/HTTP/CORS/Errors) +- [Enable CORS: I want to add CORS support to my server](https://enable-cors.org/server.html) +- {{domxref("XMLHttpRequest")}} +- [Fetch API](/en-US/docs/Web/API/Fetch_API) +- [Will it CORS?](https://httptoolkit.tech/will-it-cors) - 対話型の CORS の説明および生成 +- [How to run Chrome browser without CORS](https://alfilatov.com/posts/run-chrome-without-cors/) +- [Using CORS with All (Modern) Browsers](https://www.telerik.com/blogs/using-cors-with-all-modern-browsers) +- [Stack Overflow のよくある問題を解決するための “how to” 情報](https://stackoverflow.com/questions/43871637/no-access-control-allow-origin-header-is-present-on-the-requested-resource-whe/43881141#43881141): + + - CORS のプリフライトを防止する方法 + - CORS プロキシーを使用して「Access-Control-Allow-Origin ヘッダーの欠落」を回避する方法 + - 「Access-Control-Allow-Origin ヘッダーがワイルドカードを扱えない」ことを修正する方法 diff --git a/files/ja/web/http/cors/preflight_correct.png b/files/ja/web/http/cors/preflight_correct.png Binary files differnew file mode 100644 index 0000000000..72f9a8bf89 --- /dev/null +++ b/files/ja/web/http/cors/preflight_correct.png diff --git a/files/ja/web/http/cors/simple-req-updated.png b/files/ja/web/http/cors/simple-req-updated.png Binary files differnew file mode 100644 index 0000000000..8c3f857e7c --- /dev/null +++ b/files/ja/web/http/cors/simple-req-updated.png |