クロスサイトHTTPリクエスト、Cross-Origin Resource Sharing(CORS)の概要、withCredentialsの設定方法、検証した結果などについてまとめました。
※目次をクリックすると目次の下部にコンテンツが表示されます。
・クロスサイトHTTPリクエストとは、要求を出すリソースが存在するドメインとは異なるドメインのリソースに対してHTTPリクエストを行うことを指す。
例えば、ドメインA(http://domaina.example)にて読み込まれたHTMLページなどから、img要素(http://domainb.foo/image.jpg)を用いてドメインB(http://domainb.foo)上の画像に対するHTTPリクエストが発行される、という状況を指す。
・クロスサイトHTTPリクエストについては、セキュリティ上の理由から、同一生成元ポリシー(same-origin policy)の制約を受ける。
これによって、XMLHttpRequestを使用したwebアプリケーションは自身が読み込まれたドメインにのみHTTP リクエストを発行でき、他のドメインには発行できなくなる。
●Cross-Origin Resource Sharing(CORS)勧告
・web サーバーがサイトを跨ぐアクセスを制御する方法を規定することで、サイト間での安全な通信を保証する。
①サンプルコードの概要
・オリジナルのURL
http://192.168.1.2/ng/online/admin1.html
・オリジナルのリソースからのHTTPリクエスト(クロスドメインHTTPリクエスト)
$http.post(“http://localhost/ng/online/php/login1.php”, postData)
②結果
このサンプルコードでは、application/x-www-form-urlencoded、multipart/form-data、またはtext/plain以外のContent-TypeとともにPOST通信をクロスサイトに対して行っているので、HTTPのoptionsメソッドによる”プリフライト”リクエストを行う。
“プリフライト”リクエストは、始めに実際のリクエストを送信しても安全かを確かめるために他ドメインのリソースへ向けてHTTPのOPTIONSリクエストヘッダを送信する。
(HTTPリクエストヘッダー抜粋)
OPTIONS /ng/online/php/login1.php HTTP/1.1
Host: localhost
:
Origin: http://192.168.1.2
Access-Control-Request-Method: POST
Access-Control-Request-Headers: content-type
:
サーバー側でこのOriginのメソッドやヘッダーを許可する設定を行っていないので、POSTデータを送信しない。
2)クロスサイトHTTPリクエストをサーバー側で許可した場合
①サンプルコードの概要
・クライアント側)
上記と同じ
・サーバー側、PHP)
if($_SERVER['HTTP_ORIGIN'] == "http://192.168.1.2") { header('Access-Control-Allow-Origin: http://192.168.1.2'); header('Access-Control-Allow-Methods: POST, GET, OPTIONS'); header('Access-Control-Allow-Headers: Content-Type'); }
Originが”http://192.168.1.2″の場合は、クロスサイトリクエストを許可するために、Originやメソッド、Content-Typeをレスポンスヘッダーに指定して”プリフライト”に対して応答する。
②結果
プリライトリクエストに対して、下記のように許可する応答が返り、その後POST通信が行われる。
(HTTPレスポンスヘッダー抜粋)
HTTP/1.1 200 OK
:
Access-Control-Allow-Origin: http://192.168.1.2
Access-Control-Allow-Methods: POST, GET, OPTIONS
Access-Control-Allow-Headers: Content-Type
Access-Control-Allow-Credentials: true
3)クッキーなどクレデンシャルを含むリクエストの場合
・クロスサイトリクエストの場合、デフォルトではクッキー情報などクレデンシャルは送信されない。
・クレデンシャルを送信したい場合は、クライアント側でwithCredentialsのフラグをONにして送信する必要がある。
・ブラウザは、上記HTTPリクエストに対するレスポンスに”Access-Control-Allow-Credentials: true”が設定されていない場合は、レスポンスを拒否する。
つまり、クライアントとサーバーの両方でCredentialsのフラグをONにする必要がある。
●検証に使ったサンプルコード抜粋
(AngularJS) var myApp = angular.module('onlineStoreAdmin', ['ngRoute','ngCookies']); myApp.controller('loginCtrl', function ($scope,$http,$location,loginUrl,$cookieStore) { $cookieStore.put("name","my name"); : $http.post("http://localhost/ng/online/php/login1.php", postData, {withCredentials: true}) (サーバー側 PHP) if($_SERVER['HTTP_ORIGIN'] == "http://192.168.1.2") { header('Access-Control-Allow-Origin: http://192.168.1.2'); header('Access-Control-Allow-Methods: POST, GET, OPTIONS'); header('Access-Control-Allow-Headers: Content-Type'); header('Access-Control-Allow-Credentials: true'); }
上記のようにクライアントとサーバー側の両方でCredentialsのフラグをOnにするとクロスサイトにクッキーを送信する事が出来る。
参考サイト
HTTP access control (CORS) | MDN
Server-Side Access Control – HTTP | MDN