クロスオリジンリソースシェアリングについて
■クロスオリジンリソースシェアリング(CORS)について
Cross-Origin Resource Sharing(CORS)は、HTML5 世代の仕様です。
W3Cにより、仕様が勧告されています。
http://www.w3.org/TR/cors/
■生成元(オリジン)について
生成元(オリジン)とは、自身のリソースが格納されている場所です。
「プロトコル、ドメイン、ポート番号」の3つを合わせたものです。
■同一生成元ポリシー (Same-Origin Policy) による制限
任意の Web ページから、別オリジン下に格納されている一部のリソースを、読み取りアクセスする事はできません。
例えば、XMLHttpRequest は、受信に失敗します。
例えば、Web フォントは、ダウンロードに失敗します。
■リソースシェアリングを許可するには?
サーバー側にて、アクセスコントロール情報を、付加する事ができます。
この設定を行うと、別のオリジン下のコンテンツから、自身のサーバのリソースが読み取りアクセスされる事を許します。
リソースシェアリングを許可するには、Access-Control-Allow-Origin ヘッダを使用します。
■サーバー側のセキュリティについて
クロスオリジンリソースシェアリングは、アクセスの遮断はできません。
ブラウザが自主的にデータを受信しないだけであり、ソケット接続などからアクセスを試みるとデータの受信は可能です。
よって、公開する機密情報の取り扱いに注意します。
■静的なアクセスコントロールの設定
■ .htaccess ファイルを使用する
「http://sub.example.com:8080」からのみ、リソースシェアリングを許す
Header append Access-Control-Allow-Origin: "http://sub.example.com:8080"
「http://aaa.com」と「http://bbb.com」からのみ、リソースシェアリングを許す
Header append Access-Control-Allow-Origin: "http://aaa.com http://bbb.com"
すべてのサイトから、リソースシェアリングを許す
Header append Access-Control-Allow-Origin: "*"
■動的なアクセスコントロールの設定
■CGI から、レスポンスヘッダを出力する
プリフライトリクエストに対応する場合、CGI が必要です。
CGI を使って、動的にレスポンスヘッダを出力します。
クライアントからは、Origin ヘッダなどの、リクエスト情報が送られてきます。
すべてのサイトから、リソースシェアリングを許す (Perl)
#!/usr/local/bin/perl
print "Access-Control-Allow-Origin: *\n";
print "Content-type: text/plain\n";
print "\n";
print "Hallo World!!";
すべてのサイトから、リソースシェアリングを許す (PHP)
<?php
header("Access-Control-Allow-Origin: *");
header("Content-type: text/plain");
echo "Hallo World!!";
?>
すべてのサイトから、リソースシェアリングを許す (Ruby)
#!/usr/local/bin/ruby
print "Access-Control-Allow-Origin: *\n"
print "Content-type: text/plain\n"
print "\n"
print "Hallo World!!"
すべてのサイトから、リソースシェアリングを許す (Python)
#!/usr/local/bin/python
# coding: utf-8
# ライブラリをロード
import sys
# Content-type を出力
sys.stdout.write("Access-Control-Allow-Origin: *\n")
sys.stdout.write("Content-type: text/plain\n")
sys.stdout.write("\n")
sys.stdout.write("Hallo World!!")
アクセスコントロールについて
■アクセスコントロールの種類について
■レスポンスヘッダ(サーバー側)
| ヘッダフィールド名 | 説明 | 必須 |
| Access-Control-Allow-Origin | 許可するオリジンを設定する | ○ |
| Access-Control-Allow-Methods | 許可する HTTP メソッドの種類を設定する | |
| Access-Control-Allow-Headers | 許可するリクエストヘッダの種類を設定する | |
| Access-Control-Allow-Credentials | 認証情報の有無を設定する | |
| Access-Control-Max-Age | プリフライトの有効時間を指定する(単位:秒) | |
| Access-Control-Expose-Headers | 要求するリクエストヘッダの種類を、オープンに公開する |
■リクエストヘッダ(クライアント側)
| ヘッダフィールド名 | 説明 |
| Origin | リクエスト側のオリジン情報を、サーバ側に通知する (自動) |
| Access-Control-Request-Method | メインの HTTP メソッドの種類を、サーバ側に通知する (自動) |
| Access-Control-Request-Headers | 改変したリクエストヘッダの種類を、サーバ側に通知する (自動) |
■「Access-Control-Allow-Origin」について
クライアント側の生成元(オリジン)を指定するには、Access-Control-Allow-Origin ヘッダを使用します。
指定したオリジンのコンテンツから、リソースをシェアされる事を許可します。
それ以外は、全て拒絶します。
複数のオリジンを指定したい場合、空白で区切ります。
すべてのオリジンを許可したい場合、『 * 』を指定します。
「http://sub.example.com:8080」のみ、リソースシェアリングを許す
Access-Control-Allow-Origin: "http://sub.example.com:8080"
「http://aaa.com」と「http://bbb.com」のみ、リソースシェアリングを許す
Access-Control-Allow-Origin: "http://aaa.com http://bbb.com"
すべてのサイトから、リソースシェアリングを許す
Access-Control-Allow-Origin: *
■「Access-Control-Allow-Methods」について
HTTP メソッドの種類を指定するには、Access-Control-Allow-Methods ヘッダを使用します。
安全ではないメソッドが、コントロールの対象となります。(PUT, DELETE など)
単純なメソッドは、常に許可されます。(GET, POST, HEAD, OPTIONS など)
複数の HTTP メソッドを指定したい場合、『 , 』で区切ります。
■ヘッダ例(サーバ側)
PUT メソッドを許可する
Access-Control-Allow-Methods: PUT
PUT と DELETE と PATCH メソッドを許可する
Access-Control-Allow-Methods: PUT, DELETE, PATCH
■プリフライトリクエストについて(クライアント側)
安全ではない HTTP メソッドを指定し、さらにクロスオリジン通信となる場合、プリフライトリクエストが発生します。
まず OPTIONS メソッドで通信を行い、次に、通常の XHR 通信が発生するようになります。
■「Access-Control-Allow-Headers」について
リクエストヘッダの種類を指定するには、Access-Control-Allow-Headers ヘッダを使用します。
この設定は、プリフライト用です。
OPTIONS メソッドで通信した場合のみ影響があります。
それ以外のメソッドで通信した場合、設定に関係なくすべて許可されます。
■ OPTIONS メソッドで通信した場合
リクエストヘッダ内に、指定したヘッダ情報が含まれない場合、拒絶します。
複数のリクエストヘッダを指定したい場合、『 , 』で区切ります。
複数指定した場合、1つでも抜けがあると拒絶します。
■ヘッダ例(サーバ側)
「X-Unknown」ヘッダが含まれる場合のみ許可する(OPTIONS メソッド通信時のみ)
Access-Control-Allow-Headers: "X-Unknown"
「X-Unknown-0」と「X-Unknown-1」ヘッダが両方含まれる場合のみ許可する(OPTIONS メソッド通信時のみ)
Access-Control-Allow-Headers: "X-Unknown-0, X-Unknown-1"
■プリフライトリクエストについて(クライアント側)
リクエストヘッダ情報を改変し、さらにクロスオリジン通信となる場合、プリフライトリクエストが発生します。
まず OPTIONS メソッドで通信を行い、次に、通常の XHR 通信が発生するようになります。
リクエストヘッダにカスタム情報を追加する
// ------------------------------------------------------------
// XMLHttpRequest オブジェクトを作成
// ------------------------------------------------------------
var xhr = new XMLHttpRequest();
// ------------------------------------------------------------
// XHR 通信が成功したときに実行されるイベント
// ------------------------------------------------------------
xhr.onload = function(e){
// 出力テスト
console.log(e);
};
// ------------------------------------------------------------
// 「GET メソッド」「接続先 URL」を指定
// ------------------------------------------------------------
xhr.open("GET" , "http://example.com/test.cgi");
// ------------------------------------------------------------
// リクエストヘッダにカスタム情報を追加する
// ------------------------------------------------------------
xhr.setRequestHeader("X-Unknown-0" , "Hello");
xhr.setRequestHeader("X-Unknown-1" , "World");
// ------------------------------------------------------------
// XHR 通信を開始する
// ------------------------------------------------------------
xhr.send(null);
■「Access-Control-Allow-Credentials」について
認証情報の有無を指定するには、Access-Control-Allow-Credentials ヘッダを使用します。
true か false を指定します。
true を指定した場合、認証情報の有無に関係なく許可します。
false を指定した場合、認証情報が有る場合は拒絶し、無い場合は許可します。
省略した場合、false の指定と同じです。
このヘッダを追加した場合、「Access-Control-Allow-Origin」で指定するオリジンは、1つである必要がります。
例えば、クライアントから送られてきた、Origin ヘッダの値を、そのまま出力します。
■ヘッダ例(サーバ側)
認証情報の有無に関係なく許可する
Access-Control-Allow-Credentials: true
認証情報が有る場合は拒絶し、無い場合は許可する
Access-Control-Allow-Credentials: false
■ XHR 通信に認証情報を含める場合(クライアント側)
XMLHttpReqest クラスの withCredentials プロパティを使用します。
デフォルトでは、false です。
true を指定した場合、Cookie などの認証情報を送信するようになります。
この設定は、クロスオリジン通信時にのみ作用します。
withCredentials プロパティに true をセットした場合、「Access-Control-Allow-Credentials」ヘッダにも、true の指定が必要です。
Cookie などの認証情報を送信する(HTML5 世代)
// ------------------------------------------------------------
// XMLHttpRequest オブジェクトを作成
// ------------------------------------------------------------
var xhr = new XMLHttpRequest();
// ------------------------------------------------------------
// XHR 通信が成功したときに実行されるイベント
// ------------------------------------------------------------
xhr.onload = function(e){
// 出力テスト
console.log(e);
};
// ------------------------------------------------------------
// 「GET メソッド」「接続先 URL」を指定
// ------------------------------------------------------------
xhr.open("GET" , "http://example.com/test.cgi");
// ------------------------------------------------------------
// Cookie などの認証情報を送信する
// ------------------------------------------------------------
xhr.withCredentials = true;
// ------------------------------------------------------------
// XHR 通信を開始する
// ------------------------------------------------------------
xhr.send(null);
■「Access-Control-Max-Age」について
プリフライトの有効時間を指定するには、Access-Control-Max-Age ヘッダを使用します。
指定する数値の単位は、秒です。
指定時間内の場合、プリフライトリクエスト処理が、発生しなくなります。
以下のレスポンスヘッダ情報が、キャッシュされます。
| ヘッダフィールド名 | 説明 |
| Access-Control-Allow-Methods | 許可する HTTP メソッドの種類を設定する |
| Access-Control-Allow-Headers | 許可するリクエストヘッダの種類を設定する |
■ヘッダ例(サーバ側)
プリフライトの有効時間を 300 秒とする
Access-Control-Max-Age: 300