XMLHttpRequestが Same-Origin Policy の対象となった場合の動作を確認した

XMLHttpRequest(以降「XHR」と表記)が Same-Origin Policyの対象となった場合の動作を実際にリクエストを送信し、動作を確認しました。

今回はSame-Origin Policy周りの検証をしていくにあたっての第一弾として、今後はもう少し踏み込んだ内容でやっていく予定です。

Same-Origin Policy(SOP)とは

Same-Origin Policy(以降「SOP」と表記) は、日本語では、同一オリジンポリシー同一生成元ポリシーなどと呼ばれています。 あるオリジン(スキーム、ホスト、ポートの組み合わせ)から読み込まれた文書やスクリプトについて、そのリソースから他のオリジンのリソースにアクセスできないように制限するものです。 逆に、同じオリジンであれば、制限なしにアクセスが行えます。

今回は、XHRのSOPの動作を確認をしていきますが、他には、DOMアクセス、Cookieに関するSOP。プラグインなどでは、Java,FlashSilverlightなどにもそれぞれ個別のSOPが存在します。

詳しくは、MDN web docsのこちらのページが参考になります。

動作を確認する

簡単な検証用webアプリケーションをSinatraで作成しました。

アプリケーションは以下のような機能をもっています。

  • 画面から好きなURI宛にXHRをGet、Postで送信することができる。
  • 画面からXHRの結果(Response BodyとStatus Code)を見ることができる。
    • Response Bodyには、送った Request Method とUserAgentを表示します。
  • ルートパスにGet、Postリクエストを送ることができ、リクエストの内容をコンソールに表示することができる。

画面はこんな感じです。バッと雑に作って確認していきます。

f:id:takapi86:20170916180051p:plain

これを、先ほど説明したアプリケーションをそれぞれポートを変えて2つ起動し、XHRでやり取りできるか、できないかを確認します。

  • http://test.example.com:4567/
  • http://test.example.com:4568/

※ホスト名は検証したものとは異なります。

同一のオリジンにXHRをしてみる

まずは、アプリケーションの機能で、画面から自分宛にXHRを送信します。

http://test.example.com:4567/tool にアクセスすると、 画面から好きなURI宛にXHRをGet、Postで送信することができるツールが開くので、 ここから、http://test.example.com:4567/宛にXHRを送信します。

結果としては、もちろんですが、リクエストの送信・レスポンスの取得が成功しました。

  • デベロッパーツールのConsoleからリクエストが送られていることを確認(Log XMLHttpRequestsを有効にしています。)
XHR finished loading: GET "http://test.example.com:4567/".
XHR finished loading: POST "http://test.exapmle.com:4567/".
  • サーバ側にXHRが届いていることを確認
GET from [Mozilla/5.0 (X11; Linux x86_64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/61.0.3163.79 Safari/537.36]
XXX.XXX.XXX.XXX - - [XX/Sep/2017:XX:XX:XX +0900] "GET / HTTP/1.1" 200 - 0.0038
POST from [Mozilla/5.0 (X11; Linux x86_64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/61.0.3163.79 Safari/537.36]
"Content-Type [text/plain]"
"Body [Request Body]"
XXX.XXX.XXX.XXX - - [XX/Sep/2017:XX:XX:XX +0900] "POST / HTTP/1.1" 200 19 0.0005
  • 検証用のアプリケーションの画面からも確認

f:id:takapi86:20170916181421p:plain

f:id:takapi86:20170916181429p:plain

異なるオリジンにXHRをしてみる

ポートを変えて同じアプリケーションを起動し、そこへXHRを送信してみます。

要求されたリソースに Access-Control-Allow-Origin ヘッダーがないので、アクセスが許可されていない旨のメッセージがブラウザに表示されました。(Get、Post両方とも同じ内容)

Failed to load http://test.example.com:4568/: No 'Access-Control-Allow-Origin' header is present on the requested resource. Origin 'http://test.example.com:4567' is therefore not allowed access.
  • リクエスト自体は、サーバ側に届いているようです。
GET from [Mozilla/5.0 (X11; Linux x86_64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/61.0.3163.79 Safari/537.36]
XXX.XXX.XXX.XXX - - [XX/Sep/2017:XX:XX:XX +0900] "GET / HTTP/1.1" 200 - 0.0005
POST from [Mozilla/5.0 (X11; Linux x86_64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/61.0.3163.79 Safari/537.36]
"Content-Type [text/plain]"
"Body [Request Body]"
XXX.XXX.XXX.XXX - - [XX/Sep/2017:XX:XX:XX +0900] "POST / HTTP/1.1" 200 19 0.0005
  • 検証用のアプリケーションの画面からも確認

Get、Postどちらも値が取得できませんでした。

f:id:takapi86:20170916181739p:plain

まとめ

異なるオリジンへは、特に対策を行わない限りXHRでResponseの値を取得することができませんでした。 また、リクエストはサーバ側に届きますが、クライアント側でレスポンスは取得できないということがわかりました。

参考

SOPに関しては、以下を参考にしました。