crossdomain.xml

本エントリーでは、FLASH Playerのセキュリティのうち外部リソースを利用する際のポリシーファイルに焦点を当てます。 ポリシーファイルとはcrossdomain.xmlを指します。なお、ソケットポリシーファイルは別の機会に投稿する予定です。クロススクリプティングに関しても別の機会に。

なお本エントリーでは、ActionScript 3.0 でパブリッシュされ、Flash Player 9.0.124.0 以降で実行されるものについて考察していきます。

セキュリティドメイン

crossdomain.xmlはセキュリティドメインと非常に密接な関係があります。swfファイルのセキュリティドメインは以下のコードで確認出来ます。

trace(flash.system.Security.sandboxType);

表示される値は表1に示した、いずれかの値となるはずです。

表1. セキュリティドメインの種類
flash.system.Security.sandboxType説明
remoteインターネット上に公開されているswfファイル
localTrustedグロバールセキュリティ設定で信頼設定にしている場所のswfとFLASHオーサリングツールから「ムービープレビュー」で再生した際のswfファイル
localWithFileグロバールセキュリティ設定で信頼設定にしていない場所のswfかつ、パブリッシュ設定で「ローカルでの再生に関するセキュリティ」を「ローカルファイルにのみアクセスする」に設定したswfファイル
localWithNetwork上記の「ローカルでの再生に関するセキュリティ」を「ネットワークにのみアクセスする」に設定したswfファイル

以降、flash.system.Security.sandboxTypeの値がremote、つまりインターネット上に公開されているswfファイルを対象に話を進めていきます。もちろん、インターネット上に公開されているswfファイルをローカルに保存して実行すればremoteではなくなります。

余談

wonderflに投稿したスクリプトを見ていただくと、flash.system.Security.sandboxTypeを出力するとremoteとなることが確認出来ます。

Flash Playerのセキュリティ

AdobeのActionScript3のドキュメントにあるFlash Player セキュリティにとても詳しく記載されています。

コンテンツのロード

Flash Player セキュリティにあるとおり、以下のメソッドは、コンテンツのロードと見なされます。

flash.display.Loader.load();
flash.media.Sound.load();
flash.net.NetStream.play();

TextFieldを使った以下のような処理も、コンテンツのロードと見なされます。

var imageURL:String = "http://fla.la/wp-content/uploads/2009/08/yappaributa75x75.jpg";
var textField:TextField = new TextField();
textField.width = 100;
textField.height = 100;
textField.htmlText = ' ';

RTMPを利用したサーバを通じて送信されたコンテンツもコンテンツのロードと見なされます。 (ただしサーバの設定によって制限をかけることも可能)

これらのメソッドや処理では特に制限なくswfファイルと別のドメインから以下の種類の外部リソースを読み込むことが可能です。

  • swfファイル
  • イメージ(JPG, GIF, PNG)
  • サウンド
  • ムービー

ロードされたメディアへのデータとしてのアクセス

Flash Player セキュリティにあるとおり、以下のメソッドは、ロードされたメディアへのデータとしてのアクセスと見なされます。

flash.display.Loader.content;
flash.display.BitmapData.draw();
flash.media.SoundMixer.computeSpectrum();
flash.media.SoundMixer.stopAll();
flash.media.Sound.id3;

つまり、以下のようなシチュエーションが、ロードされたメディアへのデータとしてのアクセスとなります。

  • ビットマップデータへのアクセス
    • ロードした画像を含むLoaderクラスのインスタンス変数contentにアクセス
    • ロードした画像をBitmapDataクラスのインスタンスメソッドdrawの引数に指定する
  • サウンドデータへのアクセス
    • ロードした音源を再生中にSoundMixerクラスのインスタンスメソッドcomputeSpectrum()を呼び出す
    • ロードした音源を再生中にSoundMixerクラスのインスタンスメソッドstopAll()を呼び出す
    • ロードした音源を含むSoundクラスのインスタンス変数id3にアクセス
  • ビデオデータへのアクセス
    • FLVファイルからロードしたビデオデータにBitmapDataクラスのインスタンスメソッドdrawの引数に指定する

データのロード

Flash Player セキュリティにあるとおり、以下のメソッドは、データのロードと見なされます。

flash.net.URLLoader.load();
flash.net.URLStream.load();

Loaderクラスのloadを使用したロードはコンテンツのロード操作と見なされるがURLLoaderのloadはコンテンツのロード操作と見なされずデータのロード操作と見なされる点に注意しましょう。

crossdomain.xmlが必要となるケースは?

  • ロードされたメディアへのデータとしてのアクセス
  • データのロード

において、外部リソースがswfファイルと他のドメインである場合、外部リソースの提供側で許可が必要となります。許可はcrossdomain.xmlを使って行うことになります。

なお他のドメインと見なされるのは以下のケースです。

  • example.comとexample.orgは別(これは当たり前)
  • chat.example.comとgame.example.comは別(サブドメインが違う)
  • example.comが192.0.2.1というIPアドレスである場合、example.comと192.0.2.1は別と見なさます

全部許可最強説

FLASHのオーサリング上では問題なかったのに、webサーバに上げたとたん外部リソースとの連携まわりが動かない!そんなとき、こんなcrossdomain.xmlを置きがちです。少なくとも以前の私はそうでした。全部許可が最強なんて言ってみたりして。







でも、これって場合によっては、セキュリティリスクを伴うのです。

また、良く分からずに、下記の記述をすることもあります。

flash.system.Security.allowDomain("*");

こちらも同様に、セキュリティリスクを伴うのです。今回はcrossdomain.xmlに焦点を当てるので、flash.system.Security.allowDomain()に関してはひとまず置いておきます。

crossdomain.xmlの仕様

crossdomain.xmlの仕様はadobeのドキュメントを読みましょう。とても詳しいです。

クロスドメインポリシーファイルは、Webクライアント(Adobe Flash Playerなど)に、複数のドメイン間でのデータ処理に関する許可を付与することができる、XML形式の文書です。 アドビ デベロッパーセンター クロスドメインポリシーファイルの仕様

デフォルトでは、サーバのルートディレクトにcrossdomain.xmlを探しに行きます。example.comドメインであればhttp://example.com/crossdomain.xmlとなります。このルートディレクトリに存在するポリシーファイルをマスターポリシーファイルと呼びます。

マスターポリシーファイル以外の例えば、http://example.com/other/crossdomain.xmlを読み込みたい場合は、以下のようになります。

Security.loadPolicyFile("http://example.com/other/crossdomain.xml");

このとき以下のような順番でポリシーファイルにアクセスします。

  1. http://example.com/crossdomain.xmlを読み込む
  2. site-control要素のpermitted-cross-domain-policies属性を確認
  3. allの場合は、http://example.com/other/crossdomain.xmlを読み込む。master-only, noneの場合は読み込まない。

(permitted-cross-domain-policies属性がby-content-type, by-ftp-filenameのケースを省略してます)

よって、別のポリシーファイルにアクセスするように指定しても、Flash Playerは必ずマスターポリシーファイルへアクセスすることに注意しましょう。

ロードされたメディアへのデータとしてのアクセスを許可する

ロードされたメディアへのデータとしてのアクセスでは、外部リソースがswfファイルと別ドメインにある場合、crossdomain.xmlの読み込みが必須となります。以下に例を示します。

flash.display.Loaderでload後にBitmapData操作したい

Loaderクラスをのloadメソッドを実行する際に、LoaderContextを指定します。LoaderContexインスタンスを作成する際には引数にtrueを与えます。こうすることでLoaderがloadメソッドを実行する際にポリシーファイルを参照するようになります。

var loader:Loader = new Loader();
var loaderContext:LoaderContext = new LoaderContext(true);

loader.load(new URLRequest("http://external.example.com/image.jpg"), loaderContext);
loader.contentLoaderInfo.addEventListener(Event.COMPLETE, function(event):void
{
    var bitmapData:BitmapData = BitmapData(100, 100, true, 0x000000);
    bitmapData.draw(loader); // drawの引数にする

    var bitmapData2:BitmapData = loader.content; // Loaderインスタンスのcontentプロパティにアクセスする
});

このとき、swfファイルがswf.example.comというドメインにあったとすると、http://external.example.com/crossdomain.xmlでは以下のように記述します。







データのロード時のcrossdomain.xml確認フロー

データのロードでは、外部リソースがswfファイルと別ドメインにある場合、crossdomain.xmlの読み込みが必須となります。その際のフローを確認して見ます。

swfからアクセスした別のdomainのAPIにアクセスする場合

swfファイルがswf.example.comにありapi.example.comのAPIを叩く例です。具体的には、URLLoaderクラスのloadメソッドを使って、外部リソースであるapi.example.comのAPIから情報を取得するようなケースです。

フローを以下に示します。

[caption id="attachment_116" align="aligncenter" width="620" caption="外部データが別ドメインにある場合のcrossdomain.xml"]外部データが別ドメインにある場合のcrossdomain.xml[/caption]

  1. swf.example.comのswfをリクエスト
  2. swfを受け取る
  3. api.example.comのcrossdomain.xmlを取得
  4. crossdomain.xmlでswf.example.comが許可されているか確認
  5. api.example.comのAPIをリクエスト
  6. APIは結果を返す

このケースで必要なcrossdomain.xmlは、http://api.example.com/crossdonain.xmlとなります。内容を以下に示します。







ポイントは外部リソースにアクセスする際にポリシーファイルの許可があれば、ブラウザはcookieも送信する点です。例えばこのケースでcrossdomain.xmlが以下のようである場合







まったく別のドメインhoge.example.orgにおいてあるswfファイルからもapi.example.comにアクセスする際、ブラウザはcookieを送信します。よって、cookieが必要なサイトの内容がhoge.example.orgにおいてあるswfファイルから見えることになりますので注意しましょう。

swfからアクセスしたAPIがリダイレクトされる場合

swfファイルがswf.example.comにありapi.example.comのAPIを叩く例です。先ほどとの違いは、api.exampl.comのAPIはレスポンスとして、example.comへのリダイレクトを返すところです。

フローを以下に示します。

[caption id="attachment_117" align="aligncenter" width="619" caption="外部データが別ドメインにありリダイレクトされる場合のcrossdomain.xml"]外部データが別ドメインにありリダイレクトされる場合のcrossdomain.xml[/caption]

  1. swf.example.comのswfをリクエスト
  2. swfを受け取る
  3. api.example.comのcrossdomain.xmlを取得
  4. crossdomain.xmlでswf.example.comが許可されているか確認
  5. api.example.comのAPIをリクエスト
  6. APIはリダイレクトを返す
  7. api.example.netのcrossdomain.xmlを取得
  8. crossdomain.xmlでswf.example.comが許可されているか確認
  9. api.example.net(リダイレクト先)のAPIをリクエスト
  10. APIは結果を返す

このケースで必要なcrossdomain.xmlは、http://api.example.com/crossdonain.xmlhttp://api.example.net/crossdonain.xmlとなります。内容を以下に示します。







まとめ

外部リソースを扱う際には、crossdomain.xmlを設置することになると思いますが、必要な箇所で必要な設定を心がけることが大事です。外部ドメインにある画像の表示だけであれば、crossdomain.xmlは必要でなくflash.display.Loaderクラスのloadメソッドを使う等、代替案も考えることをおすすめします。