Firefox3ではドメインが異なっていてもXMLHttpRequestでリクエストが出せるのをmal_blue@tumblrで知りました。
すごいじゃーんというわけでJohn Resig - Cross-Site XMLHttpRequestに書かれている使いかたを参考にちょっといじってみました。今までのXMLHttpRequestは異なるドメインのURLを引数に渡すとそもそもHTTPのリクエスト自体送られませんでしたが、Firefox3からは異なるドメインのURLを渡してもHTTPのリクエストは送信されるように仕様がかわっています。リクエストは無条件で送信されますが、帰ってきたレスポンスに、サーバ側がクロスドメインのXMLHttpRequestを許可していることが明示されているときのみ、ブラウザがレスポンスの中身をXMLHttpRequestの結果としてスクリプトに返してくれる実装になっています。サーバ側が許可していることを明示していないときはエラーになります。
サーバがクロスドメインの呼び出しを許可する方法はクロスドメインのXMLHttpRequestを許可する方法は二通りあって、Cross-Site XMLHttpRequest - MDCにまとめられていています。
Access-Controlというヘッダをつけることです。返すデータがなんであっても、レスポンスに
Access-Control: allow <*>
というヘッダがついていれば、このサーバにはXMLHttpRequestを使ってどのドメインにあるページからでも通信することができます。
特定のドメインからだけアクセスできるようにしたい場合というのはあんまりない気がしますが、下記のようにしてドメインを指定することもできます。
Access-Control: allow <*.tumblr.com>
ドメインを指定することで、指定したドメイン以外にある悪意あるコードにはリクエスト自体は送られるもののクライアントがレスポンスヘッダのAccess-Controlを見て、意図していないドメインからのリクエストであればエラー扱いにしてくれます。今まではクロスドメインのリクエスト自体が送られなかったのに、Firefox3ではどんなときでもリクエスト自体は送られるので感覚的になんか怖いのですが、悪意あるページがデータを読み出そうとするページにリクエストを送ること自体は以前からscriptタグやiframeタグを使ってもできるのでクロスドメインXMLHttpRequest固有のものではありません。Firefox3の仕様変更は、他の方法を使えば前からできたことがXMLHttpRequestでもできるようになっただけです。情報が漏洩してしまうかどうかは、悪意あるページがそうして送ったリクエストの中身がスクリプトから読み出せるかどうかの部分にあります。
<?xml version="1.0" encoding="UTF-8"?>
<?access-control allow="ejohn.org"?>
<simple><name>John Resig</name></simple>
このようにXML宣言のあと、HTTPのレスポンスヘッダに入れる場合と同様にアクセスを許可するリクエスト元のドメインを記述します。
XMLHttpRequestを許可するコードを置きました。
<?php
header('Access-Control: allow <*.tumblr.com>');
print strftime("%T", time());
?>
これをいろんなページから呼び出してみましょう。
var xhr = new XMLHttpRequest();
xhr.open("GET", "http://labs.gmo.jp/blog/ku/XSXHR.php", false);
xhr.send(null);
console.log( xhr.responseText );
Access-Control: allow <*.tumblr.com>
が含まれているのでwww.tumblr.comからはXMLHttpRequestを使うことができます。

Access-Controlヘッダで許可されていないのでエラーになります。

Access-Controlヘッダで許可されていないのにエラーにならないですが、それはXMLHttpRequest先が同じドメインのhttp://labs.gmo.jp/blog/ku/XSXHR.phpだからです。同じドメインに送れるのはふつうにできるのを忘れていました。同じドメインのときは以前と同様で無条件で許可されていて、異なるドメインのときはAccess-Controlで許可されていれば読み出せるようになっています。

XMLHttpRequestはクロスドメインでリクエストを送られるようになっています。
リクエスト自体は無条件で送ることが可能です。この無条件でクロスドメインのリクエストを送れることは以前からscriptタグ等を使って可能であり、クロスサイトXMLHttpRequestに固有の特徴ではありません。クロスサイトの通信でよく利用されるJSONPには、特定のドメインからのアクセスに限って許可するといった制御ができないのに対して、クロスサイトXMLHttpRequestではレスポンスからクライアントのスクリプトがデータを読み出せるかどうかをサーバがコントロールできる仕様になっています。
クライアント側から見た場合、いままでJSONP等の動的にDOM要素を生成するハックでクロスドメインのリクエストを出すしかなかったものが、DOM要素の生成、操作という大きなオーバーヘッドを伴うハックなしにできるようになったところがクロスサイトXMLHttpRequestの利点です。サーバ側から見た場合、いままでアクセスのコントロールがまったくできない状態だったのがAccess-Controlヘッダで制御が可能になったという利点があります。
実際のところはサポートしているブラウザがFirefox3しかないので、現状では使える場面がないといっていいと思いますが、このクロスサイトXMLHttpRequestの仕様自体はW3CにAccess Control for Cross-site Requestsとして提案されているので将来的に他のブラウザでもサポートされることがあるかもしれません。
トラックバック元エントリにこのエントリへのリンクがない場合はトラックバックを受け付けません。
http://labs.gmo.jp/mt/mt-tb.cgi/190
comments