CORS (Cross-Origin Resource Sharing) 23.1

Cross-Origin Resource Sharing (クロスオリジンリソース共有) は、Web サーバーのリソースへのアクセスを、異なるオリジンのドメインからのブラウザーアプリケーションに許可するための手法を定義するブラウザー技術の仕様です。このようなアクセスは通常、同一オリジンポリシー によって禁止されています。CORS は、クロスオリジンリクエストを許可するかどうかを決定するためにブラウザーとサーバーが対話する方法を定義します。これは柔軟性をより高めるための妥協的な方策ですが、単にそのようなリクエストをすべて許可する場合よりはセキュアです。

CORS 標準は、サーバーが許可されたオリジンのドメインにリソースアクセスを許可できる新しい HTTP ヘッダーを追加することによって機能します。ブラウザーがこのヘッダーをサポートし、規定された制限を強制します。さらに、ユーザーデータに副作用を引き起こす可能性のある HTTP リクエストメソッド (とくに、GET 以外の HTTP メソッド、あるいは POST を特定の MIME タイプと使用する場合) においては、ブラウザーは、リクエストを “プリフライト” し、HTTP の OPTIONS リクエストヘッダーを使用してサポートされているメソッドをサーバーから要請し、次に、サーバーから “承認” を受けたうえで、実際の HTTP リクエストメソッドを使用して実際のリクエストを送信する必要があります。サーバーは、“認証情報” (Cookie と HTTP 認証データを含む) をリクエストとともに送信する必要があるかどうかをクライアントに通知することもできます。

CORS は、JSONP パターンに代わる新しい手法として使用できます。JSONP は GET リクエストのみをサポートしますが、CORS はその他のタイプの HTTP リクエストもサポートします。CORS を使用することによって、Web プログラマーは、JSONP よりも効率的にエラーハンドリングを行える *XMLHttpRequest* を使用できるようになります。ほとんどの新しい Web ブラウザーで CORS がサポートされています。ただし JSONP は、CORS をサポートしていないレガシーブラウザーで機能します。

CORS と Open Commerce API 

Open Commerce API では CORS 仕様がサポートされています。

API リクエストに Origin ヘッダーが含まれている場合、そのヘッダー内のオリジンが、許可されるオリジンのリスト に照らし合わせて検証されます。このリストは、Business Manager の Open Commerce API 設定でサイトとクライアントアプリケーションごとに構成できます。ヘッダー内のすべてのオリジンが、構成されたオリジンに一致する場合、API はレスポンスヘッダー *Access-Control-Allow-Origin* にすべての許可されるオリジンを返すことによって、オリジンを確定します。また、API はレスポンスヘッダー *Access-Control-Allow-Credentials* に値 “true” を返し、クライアントに Cookie も送信するよう通知します。オリジンが、許可されるオリジンのリストに指定されていない場合、API は *Access-Control-Allow* ヘッダーをレスポンスに追加しません。これは、GET および HEAD のリクエストに対して当てはまります。PATCH、POST、PUT、および DELETE の各リクエストでは、API はタイプが *UnauthorizedOriginException* の 401 フォールトを返し、サーバー側で処理は発生しません。

“プリフライトされた” リクエストはまず、他のドメインのリソースに対して HTTP OPTIONS リクエストヘッダーを送信します。これによって実際のリクエストを送信しても安全かどうかが判断されます。クロスサイトのリクエストはユーザーデータに影響を与える可能性があるため、プリフライトされます。特に、GET または POST 以外のメソッドを使用する場合は、リクエストでプリフライトを行います。また、POST メソッドを使用して、*application/x-www-form-urlencoded, multipart/form-data*、または *text/plain* 以外の Content-Type とともにリクエストデータを送信する場合、リクエストでプリフライトを行います。たとえば、POST リクエストが *application/json, application/xml*、または *text/xml* を使用してサーバーに XML ペイロードを送信する場合は、リクエストでプリフライトを行います。

許可されるオリジンの構成 

Open Commerce API で許可されるオリジンを構成するには、次の手順を実行します:

  1. Business Manager で、管理 > サイトの開発 > Open Commerce API 設定の順に移動します。
  2. 許可されるオリジンを構成するサイトを選択します。
  3. テキストフィールドで、JSON ドキュメントでクライアントアプリケーションごとにプロパティ allowed_origins を以下のように構成します。
1{
2  "_v" : "23.1",
3  "clients":
4  [
5    {
6      "allowed_origins":["http://foo.com","https://secure.foo.com:8888"],
7      "client_id":"[your_own_client_id]",
8      "resources":
9      [
10        {
11          "resource_id":"/customers/auth",
12          "methods":["post"],
13          "read_attributes":"(**)",
14          "write_attributes":"(**)"
15        },
16        {
17          "resource_id":"/baskets",
18          "methods":["post"],
19          "read_attributes":"(**)",
20          "write_attributes":"(**)"
21        },
22        ...
23      ]
24    }
25  ]
26}

’*’ ワイルドカードはサポートされていません。

Note

例 

**例 1: ** 不明なオリジンの GET リクエスト - *Access-Control-Allow* ヘッダーがレスポンスにありません。ブラウザーは同一オリジンポリシーを強制して、このレスポンスを拒否します。

1REQUEST:
2GET /dw/shop/v23_1/products/123/availability HTTP/1.1
3Host: example.com
4Origin: http://bar.com
5
6RESPONSE:
7HTTP/1.1 200 OK
8Content-Length: 67
9Content-Type: application/json; charset=UTF-8
10Cache-Control: max-age=60,must-revalidate
11
12{
13  "id":"123",
14  "name":"Shirt",
15  "orderable":true
16}

**例 2: ** 既知のオリジンの GET リクエスト - *Access-Control-Allow* ヘッダーがレスポンスにあります。最新のブラウザーではレスポンスコンテンツが使用可能になります。

1REQUEST:
2GET /dw/shop/v23_1/products/123/availability HTTP/1.1
3Host: example.com
4Origin: http://foo.com
5
6RESPONSE:
7HTTP/1.1 200 OK
8Access-Control-Allow-Origin: http://foo.com
9Access-Control-Allow-Credentials: true
10Access-Control-Expose-Headers: location,x-dw-version-status
11Content-Length: 67
12Content-Type: application/json; charset=UTF-8
13Cache-Control: max-age=60,must-revalidate
14
15{
16  "id":"123",
17  "name":"Shirt",
18  "orderable":true
19}

**例 3: ** 不明なオリジンの POST リクエスト: プリフライト OPTIONS リクエストに *Access-Control-Allow* ヘッダーがありません。ブラウザーは 2 回目のリクエストをスキップします。

1REQUEST:
2OPTIONS /dw/shop/v23_1/baskets HTTP/1.1
3Host: example.com
4Origin: http://bar.com
5Access-Control-Request-Method: POST
6Access-Control-Request-Headers: Content-Type
7
8RESPONSE:
9HTTP/1.1 204 No Content
10Allow: POST

**例 4: ** 既知のオリジンの POST リクエスト: プリフライト OPTIONS リクエストのレスポンスに *Access-Control-Allow* ヘッダーがあります。ブラウザーは 2 回目のリクエストを実行します。

1REQUEST 1:
2OPTIONS /dw/shop/v23_1/baskets HTTP/1.1
3Host: example.com
4Origin: http://foo.com
5Access-Control-Request-Method: POST
6Access-Control-Request-Headers: Content-Type
7
8RESPONSE 1:
9HTTP/1.1 204 No Content
10Access-Control-Allow-Methods: POST
11Access-Control-Max-Age: 86400
12Access-Control-Allow-Origin: http://foo.com
13Access-Control-Allow-Credentials: true
14Access-Control-Allow-Headers: Content-Type
15Allow: POST
16
17REQUEST 2:
18POST /dw/shop/v23_1/baskets HTTP/1.1
19Host: example.com
20Origin: http://foo.com
21Authorization:Bearer eyJfdiI6IjXXXXXX.eyJfdiI6IjEiLCJleHAXXXXXXX.-d5wQW4c4O4wt-Zkl7_fiEiALW1XXXX
22Content-Type: application/json
23Content-Length: 67
24
25{
26  "product_id" : "456",
27  "quantity" : 1.00
28}
29
30RESPONSE 2:
31HTTP/1.1 200 OK
32Access-Control-Allow-Origin: http://foo.com
33Access-Control-Allow-Credentials: true
34Access-Control-Expose-Headers: location,x-dw-version-status
35Content-Type: application/json;charset=UTF-8
36Cache-Control: max-age=0,no-cache,no-store,must-revalidate
37Content-Length: 158
38
39{
40  "_v" : "23.1",
41  "_resource_state" : "ba4e84383e1790597e49eeee34b201633d80ed3f499992f5af11d639dd903a36"
42  "currency" : "USD",
43  "product_sub_total" : 40.00,
44  "product_total" : 40.00,
45  "shipping_total" : null,
46  "tax_total" : null,
47  "order_total" : null,
48  "product_items" :
49  [
50    {
51      "product_id" : "456",
52      "item_text" : "Product foo",
53      "quantity" : 1.00,
54      "product_name" : "foo",
55      "base_price" : 40.00,
56      "price" : 40.00
57    }
58  ]
59}

DID THIS ARTICLE SOLVE YOUR ISSUE?
Let us know so we can improve!