-
Notifications
You must be signed in to change notification settings - Fork 1
CORS
ローカル環境( https://localhost/app )で開発を進めていると、
サーバ側( https://api.example.com/xxx )のAPIを呼び出せない や Canvas.toBlob() が実行できない という問題が発生します。
これはブラウザのセキュリティ機構の一つで、CORS ( Cross-Origin Resource Sharing ) と呼ばれており、ドメイン間をまたいだ通信をしようとする時は、予めサーバ側で許可をしておかないと通信がブロックされてしまいます。
一般的には、以下のいずれかの方法で回避が可能です。
- 方法1. 適切なHTTPレスポンスヘッダを付与する
- 方法2. Chrome の拡張機能で制限を突破する
- 方法3. Chrome Canary をオプション付きで起動し突破する
- 方法4. Nginx の proxy で突破する
クロスオリジンの通信を成立させるためには、サーバ側が返すレスポンスに以下のHTTPヘッダを付与する必要があります。
-
Access-Control-Allow-Origin: <FQDN> | *
を追加する- 特定のドメイン(
https://example.com
)か、全てのドメイン(*
)を許可するようにヘッダを設定できます - FQDN か "*" のみ許可されます。カンマで復数のドメインやサブドメインを列挙することはできません(エラーになります)
- "https://*.example.com" はエラーになります
- "example.com" はFQDNではないためエラーになります。"https://example.com" とします
- "https://example.com" と設定した場合は、サブドメインの "https://www.example.com" からのアクセスは許可されません
- "https://api.example.com" と設定した場合も、サブドメインの "https://www.example.com" からのアクセスは許可されません
-
*
を使う時は Cookie が利用できなくなります、つまり Access-Control-Allow-Credentials: true は利用できなくなります -
*
を使うとセキュリティの強度が下がるため、別途IPアドレスによるアクセス制限などを設定する必要があるでしょう
- 特定のドメイン(
-
Access-Control-Allow-Methods: <METHOD>, ...
を追加する- 許可するメソッド(GET, POST, OPTIONS, ...) をカンマ区切りで設定します
- OPTIONS も許可してください。OPTIONS はプリフライトアクセスで使用します
-
Access-Control-Allow-Headers: Origin, Authorization, Accept
を追加する -
Access-Control-Allow-Credentials: true
を追加する- これは必須ではなく Cookie 付きでアクセスをしたい場合に必要です
- true にした場合は
Access-Control-Allow-Origin: *
を指定できなくなります
まとめると、全オリジンからのAPIの呼び出しを許可する場合は、サーバ側のレスポンスに以下のヘッダを含めるように設定してください。
Access-Control-Allow-Origin: *
Access-Control-Allow-Methods: POST, GET, OPTIONS
Access-Control-Allow-Headers: Origin, Authorization, Accept, Cache-Control, Content-Type, DNT, If-Modified-Since, Keep-Alive, User-Agent, X-Requested-With
Cookie が必要な場合は Access-Control-Allow-Origin にFQDN を指定しドメインを制限することになります。また Access-Control-Allow-Credentials: true が必要になります。
Access-Control-Allow-Origin: https://api.example.com # [!] * を指定できなくなります
Access-Control-Allow-Methods: POST, GET, OPTIONS
Access-Control-Allow-Headers: Origin, Authorization, Accept, Cache-Control, Content-Type, DNT, If-Modified-Since, Keep-Alive, User-Agent, X-Requested-With
Access-Control-Allow-Credentials: true # [!] これが必要になります
上記のように、Access-Control-Allow-Origin: https://api.example.com を設定してしまうと、 https://localhost から https://api.exmple.com を呼べなくなります(ブラウザ側でエラーにされてしまいます)。
このようなケースでは後述の Chrome Canary をオプション付きで起動し突破する を使用するか、 後述するSubdomain CORSを使い nginx で Access-Control-Allow-Origin を動的に生成してください。
復数のサブドメインや無関係なドメインからのアクセスを許可する場合は Access-Control-Allow-Origin ヘッダを動的に書き換える必要があります。
以下の例では https://api.example.com に対し https://www.example.com や https://ope.example.com そして https://localhost からのアクセスを許可しています。
server {
listen 443;
server_name api.example.com;
location / {
if ($http_origin ~* (https://(www\.example\.com|ope\.example\.com|localhost))) { #
set $cors "true";
}
if ($cors = "true") {
add_header Access-Control-Allow-Origin "$http_origin" always;
add_header Access-Control-Allow-Methods "POST, GET, OPTIONS";
add_header Access-Control-Allow-Headers "Access-Control-Allow-Headers: Origin, Authorization, Accept, Cache-Control, Content-Type, DNT, If-Modified-Since, Keep-Alive, User-Agent, X-Requested-With";
add_header Access-Control-Allow-Credentials true;
}
}
}
always は 200 以外(404や500) の場合にも CORS ヘッダを付与するパラメタです。 always を付けないと 404 でも CORS のエラーとしてブラウザがステータスコードを書き換えてしまい、404 かどうかが分からなくなります(エラー原因の調査が難航します)。
Chrome の拡張機能をインストールし、Allow-Control-Allow-Origin ヘッダ等を付与することで、ブラウザの制限突破を試みます。
最新のChrome は Access-Control-Allow-Origin
に復数の要素を指定するとエラーになります(例1, 例2)。
Chrome の拡張機能を使って、レスポンスヘッダを書き換える(追加する)場合に、サーバからのレスポンスヘッダに既に Access-Control-Allow-Origin: ... が含まれていると、この症状が発生しエラーになってしまいます。 その場合は、サーバ側の設定を変更するか、この方法を諦めて後述の Chrome Canary をオプション付きで起動し突破する を使用してください。
例1 (Access-Control-Allow-Origin の指定にカンマが許されなくなった)
Access-Control-Allow-Origin: https://example.com, *
例2 (Access-Control-Allow-Origin を何度か呼ぶことでも同様に発生する)
Access-Control-Allow-Origin: https://example.com
Access-Control-Allow-Origin: *
Chrome Canary を全て終了させ、以下のコマンドを実行すると、 CORS が OFF になっている状態で起動します。
open -a Google\ Chrome\ Canary --args \
--allow-cross-origin-auth-prompt \
--disable-web-security \
--user-data-dir ~/ \
--flag-switches-begin \
--enable-experimental-web-platform-features \
--flag-switches-end
一行: open -a Google\ Chrome\ Canary --args --allow-cross-origin-auth-prompt --disable-web-security --user-data-dir ~/ --flag-switches-begin --enable-experimental-web-platform-features --flag-switches-end
この方法で起動すると素の Chrome Canary が起動します。
Chrome Canary を普段使いしている方は注意してください。
ブックマークバーが非表示になっていたり、開いていたタブが全滅したりします。Chrome Canary の生き残りがいると設定が反映されません。
Dock に常駐している Chrome Canary も終了させてください。
Nginx の proxy で頑張る方法です。
- Install and Setup
- Devlopment (TODO)
- Distribution
- Deployment (TODO)
- Application Structure
- Idioms
- Troubleshooting
- Keywords