クロスサイト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
- ビルトインのディレクティブの概要
- データバインディングのディレクティブの概要
- ng-repeatを使ってリスト、テーブル、フィルター
- ng-includeを使って別のHTMLファイルを埋め込み
- ng-switchを使って内部にあるHTMLテンプレートの表示を切り替え
- ng-if、ng-show、ng-hideを使って表示、非表示を切り替え
- ng-class、ng-styleを使ってCSSを設定
- イベント処理
- 有効、無効を切替えるディレクティブ
- フォームの入力チェックを行い、動的にCSS追加
- ng-optionsを使ってSelectメニューを作成
- ng-repeatを使ってラジオボタンを作成
- ビルトインのフィルターの使用方法
- ビルトインのフィルターで関数を使用
- カスタムフィルターの使用方法
- Bootstrap3を使ってページング
- スクリプト内でフィルターを使用、既存のフィルターを拡張
- サービスの概要とfactory、service、providerの使い分け
- $qサービスでpromise/deferredパターン
- $httpサービスの概要、サーバーからJSONデータ取得
- $httpサービスのPOSTでデータ送信
- $qサービスを使ってhttpリクエストを複数実行
- $httpサービスのinterceptorの使用方法
- AngularJSのwithCredentialsの設定、CORS
- $timeoutサービスと$intervalサービス
- $resourceサービスを使ってREST
- $locationサービスを使ってURLを操作
- $routeサービスと$resourceサービスを使ったサンプルを作成
- routeChangeSuccessを使ってflashメッセージ表示
- JavaScript、CSSを含むHTMLデータをバインドして表示
- ビルトインのディレクティブの概要
- データバインディングのディレクティブの概要
- ng-repeatを使ってリスト、テーブル、フィルター
- ng-includeを使って別のHTMLファイルを埋め込み
- ng-switchで内部にあるHTMLテンプレートの表示を切り替え
- ng-if、ng-show、ng-hideを使って表示、非表示を切り替え
- ng-class、ng-styleを使ってCSSを設定
- イベント処理
- 有効、無効を切替えるディレクティブ
- フォームの入力チェックを行い、動的にCSS追加
- ng-optionsを使ってSelectメニューを作成
- ng-repeatを使ってラジオボタンを作成
- ビルトインのフィルターの使用方法
- ビルトインのフィルターで関数を使用
- カスタムフィルターの使用方法
- Bootstrap3を使ってページング
- スクリプト内でフィルターを使用、既存のフィルターを拡張
- サービスの概要とfactory、service、providerの使い分け
- $qサービスでpromise/deferredパターン
- $httpサービスの概要、サーバーからJSONデータ取得
- $httpサービスのPOSTでデータ送信
- $qサービスを使ってhttpリクエストを複数実行
- $httpサービスのinterceptorの使用方法
- AngularJSのwithCredentialsの設定、CORS
- $timeoutサービスと$intervalサービス
- $resourceサービスを使ってREST
- $locationサービスを使ってURLを操作
- $routeサービスと$resourceサービスを使ったサンプルを作成
- routeChangeSuccessを使ってflashメッセージ表示
- JavaScript、CSSを含むHTMLデータをバインドして表示