aboutsummaryrefslogtreecommitdiff
path: root/files/ja/web/http/cors/index.html
blob: 33d046aaeddc96ca51a9cdc9022ddd46a05e0f85 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
444
445
446
447
448
449
450
451
452
453
454
455
456
457
458
459
460
461
462
463
464
465
466
467
468
469
470
471
472
473
474
475
476
477
478
479
480
481
482
483
484
485
486
487
488
489
490
491
492
493
494
495
496
497
498
499
500
501
502
---
title: オリジン間リソース共有 (CORS)
slug: Web/HTTP/CORS
tags:
  - AJAX
  - CORS
  - Fetch
  - Fetch API
  - HTTP
  - HTTP アクセス制御
  - Security
  - XMLHttpRequest
  - 'l10n:priority'
  - オリジン間リソース共有
  - セキュリティ
  - 同一オリジンポリシー
translation_of: Web/HTTP/CORS
---
<div>{{HTTPSidebar}}</div>

<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>

<p>オリジン間リクエストの一例: <code>https://domain-a.com</code> で提供されているウェブアプリケーションのフロントエンド JavaScript コードが {{domxref("XMLHttpRequest")}} を使用して <code>https://domain-b.com/data.json</code> へリクエストを行う場合。</p>

<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>

<p><img alt="" src="https://mdn.mozillademos.org/files/14295/CORS_principle.png" style="height: 643px; width: 925px;"></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>

<p>誰もが読むべきです。</p>

<p>もっと具体的に言えば、この記事は<strong>ウェブ管理者</strong><strong>サーバー開発者</strong><strong>フロントエンド開発者</strong>向けです。最近のブラウザーはヘッダーやポリシーの強制を含む、オリジン間共有のクライアント側コンポーネントを扱います。しかし CORS 標準は、サーバーが新たなリクエストヘッダーやレスポンスヘッダーを扱わなければならないことを示しています。サーバー開発者向けには、<a href="/ja/docs/Web/HTTP/Server-Side_Access_Control">サーバーの観点によるオリジン間共有 (PHP コードスニペット付き)</a> についての議論を合わせてお読みください。</p>

<h2 id="What_requests_use_CORS" name="What_requests_use_CORS">CORS を使用したリクエストとは</h2>

<p>この<a class="external" href="https://fetch.spec.whatwg.org/#http-cors-protocol">オリジン間共有仕様</a>は、以下のようなサイト間 HTTP リクエストを有効にすることができます。</p>

<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>

<h2 id="Functional_overview" name="Functional_overview">機能概要</h2>

<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>

<p>CORS は様々なエラーで失敗することがありますが、セキュリティ上の理由から、エラーについて <em>JavaScript から知ることができない</em>よう定められています。コードからはエラーが発生したということしか分かりません。何が悪かったのかを具体的に知ることができる唯一の方法は、ブラウザーのコンソールで詳細を見ることです。</p>

<p>以降の節ではシナリオの説明に加え、 HTTP ヘッダーの使い方の詳細も提供します。</p>

<h2 id="Examples_of_access_control_scenarios" name="Examples_of_access_control_scenarios">アクセス制御シナリオの例</h2>

<p>オリジン間リソース共有がどのように動作するかを説明する3つのシナリオを示します。これらの例はすべて {{domxref("XMLHttpRequest")}} を用いており、対応しているブラウザーにおいて、サイトをまたいでアクセスすることができます。</p>

<p>サーバー側から見たオリジン間リソース共有の説明 (PHP のコードスニペットを含む) は <a class="internal" href="/ja/docs/Web/HTTP/Server-Side_Access_Control">Server-Side Access Control (CORS)</a> の記事にあります。</p>

<h3 id="Simple_requests" name="Simple_requests">単純リクエスト</h3>

<p>リクエストによっては <a href="#Preflighted_requests">CORS プリフライト</a>を引き起こさないものがあります。これをこの記事では<em>「単純リクエスト」</em>と呼んでいますが、 (CORS を定義している) {{SpecName('Fetch')}} 仕様書ではこの用語を使用していません。 「単純リクエスト」は、<strong>以下のすべての条件を満たす</strong>ものです。</p>

<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>

<div class="note"><strong>注:</strong> これらはウェブコンテンツが発行可能になっているサイト間リクエストと同じ種類のものであり、サーバーが適切なヘッダーを送信しなければレスポンスデータは送信元へ送られません。従ってクロスサイトリクエストフォージェリ対策をしているサイトは、 HTTP アクセス制限について新たに心配することはありません。</div>

<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>

<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>

<p>これは仕様の一部ではないので、他のブラウザーはこの追加の制限を実装していません。</p>
</div>

<p>例えば、ドメイン <code class="plain">https://foo.example</code> にあるウェブコンテンツがドメイン <code class="plain">https://bar.other</code> にあるコンテンツを呼び出したいと仮定します。以下のようなコードが <code>foo.example</code> 内の JavaScript で使用されるかもしれません。</p>

<pre class="brush: js notranslate" id="line1">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>

<p><img alt="" src="https://mdn.mozillademos.org/files/17214/simple-req-updated.png" style="height: 490px; width: 1023px;"></p>

<p>この場合、ブラウザーがサーバーに何を送信し、サーバーが何を返すかを見てみましょう。</p>

<pre class="brush: shell notranslate">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>

<p>特筆すべきリクエストヘッダーは {{HTTPHeader("Origin")}} であり、呼び出しが <code class="plain">https://foo.example</code> から来たことを表します。</p>

<pre class="notranslate">HTTP/1.1 200 OK
Date: Mon, 01 Dec 2008 00:23:53 GMT
Server: Apache/2
<strong>Access-Control-Allow-Origin: *</strong>
Keep-Alive: timeout=2, max=100
Connection: Keep-Alive
Transfer-Encoding: chunked
Content-Type: application/xml

[…XML データ…]</pre>

<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>

<pre class="notranslate"><code class="plain">Access-Control-Allow-Origin: https://foo.example</code></pre>

<p><code class="plain">https://foo.example</code> 以外のドメインはすべて、サイト間の方法でリソースにアクセスすることがサイト間の方法でリソースにアクセスすることができなくなりました。リソースへのアクセスを許可するには、 <code>Access-Control-Allow-Origin</code> ヘッダーに、リクエストの <code>Origin</code> ヘッダーの中で送信された値を含めてください。</p>

<h3 id="Preflighted_requests" name="Preflighted_requests">プリフライトリクエスト</h3>

<p><a href="#Simple_requests">「単純リクエスト」 (前述)</a> とは異なり、「プリフライト」リクエストは始めに {{HTTPMethod("OPTIONS")}} メソッドによる HTTP リクエストを他のドメインにあるリソースに向けて送り、実際のリクエストを送信しても安全かどうかを確かめます。サイト間リクエストがユーザーデータに影響を与える可能性があるような場合に、このようにプリフライトを行います。</p>

<p>以下は、プリフライトが行われるリクエストの例です。</p>

<pre class="brush: js notranslate" id="line1">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('&lt;person&gt;&lt;name&gt;Arun&lt;/name&gt;&lt;/person&gt;');
</pre>

<p>上記の例では、 <code>POST</code> で送信する XML の本体を作成しています。また、標準外の <code>X-PINGOTHER</code> HTTP リクエストヘッダーを設定しています。このようなヘッダーは HTTP/1.1 プロトコルに含まれていませんが、ウェブアプリケーションでは一般的に便利なものです。リクエストで <code>Content-Type</code><code>application/xml</code> を使用しており、かつカスタムヘッダーを設定しているため、このリクエストではプリフライトを行います。</p>

<p><img alt="" src="https://mdn.mozillademos.org/files/17268/preflight_correct.png" style="height: 1076px; width: 1024px;"></p>

<div class="blockIndicator note">
<p><strong></strong>: 後述するように、実際の <code>POST</code> リクエストには <code>Access-Control-Request-*</code> ヘッダーが含まれず、 <code>OPTIONS</code> リクエストのみで必要になります。</p>
</div>

<p>クライアントとサーバーとの間のやりとりの全容を見てみましょう。最初のやり取りは<em>プリフライトリクエスト/レスポンス</em>です。</p>

<pre class="brush: shell notranslate">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
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
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
Vary: Accept-Encoding, Origin
Keep-Alive: timeout=2, max=100
Connection: Keep-Alive
</pre>

<p>プリフライトリクエストが完了したら、実際のリクエストを送ります。</p>

<pre class="brush: shell notranslate">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
Accept-Language: en-us,en;q=0.5
Accept-Encoding: gzip,deflate
Connection: keep-alive
X-PINGOTHER: pingpong
Content-Type: text/xml; charset=UTF-8
Referer: https://foo.example/examples/preflightInvocation.html
Content-Length: 55
Origin: https://foo.example
Pragma: no-cache
Cache-Control: no-cache

&lt;person&gt;&lt;name&gt;Arun&lt;/name&gt;&lt;/person&gt;


HTTP/1.1 200 OK
Date: Mon, 01 Dec 2008 01:15:40 GMT
Server: Apache/2
Access-Control-Allow-Origin: https://foo.example
Vary: Accept-Encoding, Origin
Content-Encoding: gzip
Content-Length: 235
Keep-Alive: timeout=2, max=99
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>

<p>上記の13-22行目はサーバーが返すレスポンスであり、リクエストメソッド (<code>POST</code>) とリクエストヘッダー (<code>X-PINGOTHER</code>) を受け入れられることを示しています。特に、16-19行目を見てみましょう。</p>

<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>

<p>これらの変更ができない場合は、次のような別な方法があります。</p>

<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>

<h3 id="Requests_with_credentials" name="Requests_with_credentials">資格情報を含むリクエスト</h3>

<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>

<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/';

function callOtherDomain() {
  if (invocation) {
    invocation.open('GET', url, true);
    invocation.withCredentials = true;
    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>

<p><img alt="" src="https://mdn.mozillademos.org/files/17213/cred-req-updated.png" style="height: 490px; width: 1023px;"></p>

<p>以下はクライアントとサーバーとの間のやりとりの例です。</p>

<pre class="brush: shell notranslate">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
Cookie: pageAccess=2


HTTP/1.1 200 OK
Date: Mon, 01 Dec 2008 01:34:52 GMT
Server: Apache/2
Access-Control-Allow-Origin: https://foo.example
Access-Control-Allow-Credentials: true
Cache-Control: no-cache
Pragma: no-cache
Set-Cookie: pageAccess=3; expires=Wed, 31-Dec-2008 01:34:53 GMT
Vary: Accept-Encoding, Origin
Content-Encoding: gzip
Content-Length: 106
Keep-Alive: timeout=2, max=100
Connection: Keep-Alive
Content-Type: text/plain


[text/plain payload]
</pre>

<p>10行目に <code class="plain">http://bar.other</code> 向けのクッキーが含まれていますが、bar.other が {{HTTPHeader("Access-Control-Allow-Credentials")}}<code>: true</code> (17行目) をレスポンスに含めなければ、レスポンスは無視されウェブコンテンツで使用できません。</p>

<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>

<p>なお、上記の例の中にある <code>Set-Cookie</code> レスポンスヘッダーは、将来のクッキーの設定も行ないます。失敗した場合、 (使われている API によりますが) 例外が発生します。</p>

<h4 id="Third-party_cookies" name="Third-party_cookies">サードパーティーのクッキー</h4>

<p>CORS のレスポンスに設定されたクッキーは、サードパーティーのクッキーに関する通常のポリシーに従います。上記の例では、ページは <code>foo.example</code> から読み込まれていますが、20行目のクッキーは <code>bar.other</code> から送られているので、ユーザーがブラウザーでサードパーティーのクッキーをすべて拒否するよう設定していた場合は保存されません。</p>

<h2 id="The_HTTP_response_headers" name="The_HTTP_response_headers">HTTP レスポンスヘッダー</h2>

<p>ここではオリジン間リソース共有の仕様書で定義されている、アクセス制御のためにサーバーが返す HTTP レスポンスヘッダーを掲載します。前の章では、これらの実際の動作の概要を説明しました。</p>

<h3 id="Access-Control-Allow-Origin">Access-Control-Allow-Origin</h3>

<p>返却されるリソースには、以下のような構文で1つの {{HTTPHeader("Access-Control-Allow-Origin")}} ヘッダーがつくことがあります。</p>

<pre class="brush: none notranslate">Access-Control-Allow-Origin: &lt;origin&gt; | *
</pre>

<p><code>Access-Control-Allow-Origin</code> は、リソースへのアクセスを許可するオリジンをブラウザーに伝えるための単一のオリジン、または — 資格情報を<strong>含まない</strong>リクエストにおいては — どのオリジンにもリソースへのアクセスを許可することをブラウザーに伝えるワイルドカード "<code>*</code>" のどちらかを指定することができます。</p>

<p>例えば、 <code>https://mozilla.org</code> のオリジンからのコードにリソースへのアクセスを許可するには、次のように指定します。</p>

<pre class="brush: none notranslate">Access-Control-Allow-Origin: https://mozilla.org
Vary: Origin</pre>

<p>サーバーがワイルドカード "<code>*</code>" ではなく (ホワイトリストの一部としてリクエストするオリジンに基づいて動的に変更される可能性がある) 単一のオリジンを指定した場合は、サーバーは {{HTTPHeader("Vary")}} レスポンスヘッダーに <code>Origin</code> も含めて、サーバーのレスポンスが {{HTTPHeader("Origin")}} リクエストヘッダーの値によって変化することをクライアントに示してください。</p>

<h3 id="Access-Control-Expose-Headers">Access-Control-Expose-Headers</h3>

<p>{{HTTPHeader("Access-Control-Expose-Headers")}} ヘッダーは、ブラウザーがアクセスを許可されるサーバーのホワイトリストにあるヘッダーを示すことができます。</p>

<pre class="brush: none notranslate">Access-Control-Expose-Headers: &lt;header-name&gt;[, &lt;header-name&gt;]*
</pre>

<p>例えば、以下のようになります。</p>

<pre class="brush: none notranslate">Access-Control-Expose-Headers: X-My-Custom-Header, X-Another-Custom-Header
</pre>

<p>これは、ブラウザーに対して <code>X-My-Custom-Header</code> および <code>X-Another-Custom-Header</code> ヘッダーを許可します。</p>

<h3 id="Access-Control-Max-Age">Access-Control-Max-Age</h3>

<p>このヘッダーはプリフライトリクエストの結果をキャッシュしてよい時間を示します。プリフライトリクエストの例は、前出の例をご覧ください。</p>

<pre class="brush: none notranslate">Access-Control-Max-Age: &lt;delta-seconds&gt;
</pre>

<p><code>delta-seconds</code> 引数は、結果をキャッシュしてよい時間を秒単位で示します。</p>

<h3 id="Access-Control-Allow-Credentials">Access-Control-Allow-Credentials</h3>

<p>{{HTTPHeader("Access-Control-Allow-Credentials")}}<code>credentials</code> フラグが真であるときに、リクエストへのレスポンスを開示してよいか否かを示します。プリフライトリクエストのレスポンスの一部として用いられたときは、実際のリクエストで資格情報を使用してよいか否かを示します。単純な <code>GET</code> リクエストはプリフライトを行いませんので、リソースへのリクエストが資格情報付きで行われた場合にリソースと共にこのヘッダーを返さなければ、レスポンスはブラウザーによって無視され、ウェブコンテンツに返らないことに注意してください。</p>

<pre class="brush: none notranslate">Access-Control-Allow-Credentials: true
</pre>

<p><a class="internal" href="#Requests_with_credentials">資格情報付きのリクエスト</a>は前に説明したとおりです。</p>

<h3 id="Access-Control-Allow-Methods">Access-Control-Allow-Methods</h3>

<p>{{HTTPHeader("Access-Control-Allow-Methods")}} ヘッダーは、リソースへのアクセス時に許可するメソッドを指定します。これはプリフライトリクエストのレスポンスで用いられます。リクエストのプリフライトを行う条件については前述のとおりです。</p>

<pre class="brush: none notranslate">Access-Control-Allow-Methods: &lt;method&gt;[, &lt;method&gt;]*
</pre>

<p>ブラウザーにこのヘッダーを送信する例を含む、プリフライトリクエストの例は <a class="internal" href="#Preflighted_requests">前述のとおりです</a></p>

<h3 id="Access-Control-Allow-Headers">Access-Control-Allow-Headers</h3>

<p>{{HTTPHeader("Access-Control-Allow-Headers")}} ヘッダーは、実際のリクエストでどの HTTP ヘッダーを使用できるかを示すために、<a class="internal" href="#Preflighted_requests">プリフライトリクエスト</a>のレスポンスで使用します。</p>

<pre class="brush: none notranslate">Access-Control-Allow-Headers: &lt;header-name&gt;[, &lt;header-name&gt;]*
</pre>

<h2 id="The_HTTP_request_headers" name="The_HTTP_request_headers">HTTP リクエストヘッダー</h2>

<p>この節では、 HTTP リクエストを発行する際、オリジン間リソース共有機能を利用するためにクライアントが使用できるヘッダーの一覧を掲載します。なお、これらのヘッダーはサーバーの呼び出し時に設定されます。サイト間 {{domxref("XMLHttpRequest")}} の機能を使用する開発者は、オリジン間リソース共有のヘッダーをプログラムで設定する必要はありません。</p>

<h3 id="Origin">Origin</h3>

<p>{{HTTPHeader("Origin")}} ヘッダーはサイト間のアクセスリクエストやプリフライトリクエストのオリジンを示します。</p>

<pre class="brush: none notranslate">Origin: &lt;origin&gt;
</pre>

<p>origin は、リクエストを開始したサーバーを示す URI です。ここにパス情報は含めず、サーバー名だけにします。</p>

<div class="note"><strong>注:</strong> <code>origin</code> の値は <code>null</code> または URI にすることができます。</div>

<p>すべてのアクセス制御リクエストにおいて、 {{HTTPHeader("Origin")}} ヘッダーは<strong>常に</strong>送信されることに注意してください。</p>

<h3 id="Access-Control-Request-Method">Access-Control-Request-Method</h3>

<p>{{HTTPHeader("Access-Control-Request-Method")}} はプリフライトリクエストを発信する際に、実際のリクエストを行う際に使用する HTTP メソッドをサーバーに知らせるために使用します。</p>

<pre class="brush: none notranslate">Access-Control-Request-Method: &lt;method&gt;
</pre>

<p>使用例は<a class="internal" href="#Preflighted_requests">前出のとおりです</a></p>

<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: &lt;field-name&gt;[, &lt;field-name&gt;]*
</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 &amp; 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>