本エントリーでは、FLASH Playerのセキュリティのうち外部リソースを利用する際のポリシーファイルに焦点を当てます。 ポリシーファイルとはcrossdomain.xmlを指します。なお、ソケットポリシーファイルは別の機会に投稿する予定です。クロススクリプティングに関しても別の機会に。
なお本エントリーでは、ActionScript 3.0 でパブリッシュされ、Flash Player 9.0.124.0 以降で実行されるものについて考察していきます。
セキュリティドメイン
crossdomain.xmlはセキュリティドメインと非常に密接な関係があります。swfファイルのセキュリティドメインは以下のコードで確認出来ます。
trace(flash.system.Security.sandboxType);
表示される値は表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");
このとき以下のような順番でポリシーファイルにアクセスします。
- http://example.com/crossdomain.xmlを読み込む
- site-control要素のpermitted-cross-domain-policies属性を確認
- 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"][/caption]
- swf.example.comのswfをリクエスト
- swfを受け取る
- api.example.comのcrossdomain.xmlを取得
- crossdomain.xmlでswf.example.comが許可されているか確認
- api.example.comのAPIをリクエスト
- 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"][/caption]
- swf.example.comのswfをリクエスト
- swfを受け取る
- api.example.comのcrossdomain.xmlを取得
- crossdomain.xmlでswf.example.comが許可されているか確認
- api.example.comのAPIをリクエスト
- APIはリダイレクトを返す
- api.example.netのcrossdomain.xmlを取得
- crossdomain.xmlでswf.example.comが許可されているか確認
- api.example.net(リダイレクト先)のAPIをリクエスト
- APIは結果を返す
このケースで必要なcrossdomain.xmlは、http://api.example.com/crossdonain.xmlとhttp://api.example.net/crossdonain.xmlとなります。内容を以下に示します。
まとめ
外部リソースを扱う際には、crossdomain.xmlを設置することになると思いますが、必要な箇所で必要な設定を心がけることが大事です。外部ドメインにある画像の表示だけであれば、crossdomain.xmlは必要でなくflash.display.Loaderクラスのloadメソッドを使う等、代替案も考えることをおすすめします。