クロススクリプティング

本エントリーでは、FLASH Playerのセキュリティのうちクロススクリプティングに焦点を当てます。外部リソースを利用する際のポリシーファイルに関しては、fla.la » crossdomain.xmlをご覧下さい。

AdobeのFlash Playerデベロッパーセンターにある以下の記事が参考になります。

より安全なSWF Webアプリケーション

クロススクリプティングとは

fla.la » crossdomain.xmlでも紹介した通り、Flash Playerのセキュリティに関しては、AdobeのActionScript3のドキュメントのFlash Player セキュリティに詳しく掲載されています。

ではクロススクリプティングとはどんな操作を指すのかまとめてみます。

  • Loaderクラスのcontent変数を通じて、ロードしたswfファイルを参照するオブジェクトを取得する
  • ロードしたswfファイル内に定義されたプロパティにアクセスする
  • ロードしたswfファイル内に定義されたメソッドを実行する
  • ロードしたswfファイル内に定義されたクラスを参照する
  • BitmapDataクラスのdrawメソッドを通じて、ロードしたswfファイルのピクセルをBitmapDataクラスのインスタンスへコピーする
  • ロード元swfファイルのDisplayObjectツリーと、ロードしたswfファイルのDisplayObjectツリー間を移動する
  • ロード元swfファイルのDisplayObjectツリーと、ロードしたswfファイルのDisplayObjectツリー間のイベント伝達フロー

フローを確認

外部リソースをロードするswfを main.swf、外部リソースをresource.swfとします。

同一ドメインから外部リソースをロードする

swfのドメインをswf.example.comとすると、フローは以下のようになります。

同一ドメインのswfでクロススクリプティング

同一ドメインのswfでクロススクリプティング

  1. http://swf.exapmle.com/main.swfへアクセス
  2. main.swfを受け取る
  3. main.swfからhttp://swf.exapmle.com/resource.swfをロードする
  4. resource.swfを受け取る
  5. resource.swfに定義されている変数、メソッド、クラスにアクセスする

同一ドメイン内のswfファイルを扱う際には、簡単ですね。

別ドメインから外部リソースをロードする

main.swfからresource.swfをロードする2つの方法を紹介します。

  • Loaderを使う
  • URLLoaderを使う
Loaderを使う場合

外部リソースに対してクロススクリプティングを行う際には、外部リソースにおいて、ロード元のswfのドメインからのアクセスの許可が必要です。

resource.swf内では以下の記述が必要です。

Security.allowDomain("swf.example.com");

フローは以下のようになります。

別ドメインのswfでクロススクリプティング Loader

別ドメインのswfでクロススクリプティング Loader

  1. http://swf.exapmle.com/main.swfへアクセス
  2. main.swfを受け取る
  3. main.swfからhttp://other.exapmle.net/resource.swfをロードする
  4. resource.swfを受け取る
  5. resource.swfでSecurity.allowDomain(“swf.example.com”);を確認
  6. resource.swfに定義されている変数、メソッド、クラスにアクセスする
URLLoaderを使う場合

基本的に、外部リソースに対してクロススクリプティングを行う際には、外部リソースにおいて、ロード元のswfのドメインからのアクセスの許可が必要です。

但し、URLLoaderを使い、ロードしたURLLoaderインスタンスのdataプロパティをLoaderインスタンスのloadBytesメソッドに渡す事で、外部リソースに対してクロススクリプティングが可能です。

これは、LoaderインスタンスのloadBytes()メソッドでは、ロードされた SWF ファイルが常にロード元 SWF ファイルのセキュリティドメインに配置されるためです。

その際、URLLoaderインスタンスのloadメソッドは、データのロードにあたるので、外部リソースのドメインに配置したポリシーファイルにおいてロード元のドメインが許可されている必要があります。

http://other.example.net/crossdomain.xmlの内容の一例は以下のようになります。

<?xml version="1.0"?>
<!DOCTYPE cross-domain-policy SYSTEM "http://www.adobe.com/xml/dtds/cross-domain-policy.dtd">
<cross-domain-policy>
<site-control permitted-cross-domain-policies="master-only"/>
<allow-access-from domain="swf.example.com" />
</cross-domain-policy>

フローは以下のようになります。

別ドメインのswfでクロススクリプティング URLLoader

別ドメインのswfでクロススクリプティング URLLoader

  1. http://swf.exapmle.com/main.swfへアクセス
  2. main.swfを受け取る
  3. http://other.example.net/crossdomain.xmlへアクセス
  4. crossdomain.xmlを受け取る
  5. main.swfからhttp://other.exapmle.net/resource.swfをロードする
  6. resource.swfを受け取る
  7. resource.swfに定義されている変数、メソッド、クラスにアクセスする

ロードのサンプル

ここでサンプルとして、以下のようなpublicメソッドを持つ簡易アバターを作成しました。

簡易アバターのAPI
API 機能
front アバターが前を向きます
back アバターが後を向きます
left アバターが左を向きます
right アバターが右を向きます
play アバターがアニメーションします

簡易アバターのURLは以下となります。
avatar1.swfとavatar2.swfはまったく同じ機能をもったswfですが、下記の記述はavatar2.swfにしかありません。

Security.allowDomain("fla.la");

つまり、avatar2.swfはfla.laドメインに配置されたswfからパブリックメソッドを実行出来ます。

では、LoaderとURLLoaderでこれらの簡易アバターをロードしたのち、クロススクリプティングで操作するコードを紹介します。

Loaderを使う際のサンプルコード

以下をドキュメントクラスとするswfをfla.laドメインへ配置するとします。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
package  
{
	import flash.display.Loader;
	import flash.display.Sprite;
	import flash.events.Event;
	import flash.net.URLLoader;
 
	/**
	 * 外部リソースをLoaderでロードしてからメソッドにアクセス
	 * @author naoto koshikawa
	 */
	public class CrossScript1 extends Sprite
	{
		//----------------------------------------------------------------------
		//  methods
		//----------------------------------------------------------------------
		//------------------------------
		//  public methods
		//------------------------------
		/**
		 * constructor
		 */
		public function CrossScript1() 
		{
			var avatar:*;
 
			var loader:Loader = new Loader();
			loader.contentLoaderInfo.addEventListener(
				Event.COMPLETE, 
				function(event:Event):void
				{
					avatar = loader.content; // avatar1.swfだとここでエラー
					addChild(avatar);
					avatar.play();
				}
			);
			loader.load(new URLLoader("http://asmple.com/work/avatar2.swf"));
		}	
	}	
}

32行目の処理は、Loaderクラスのcontent変数を通じて、ロードしたswfファイルを参照するオブジェクトを取得することに該当するので、外部リソースのswfでSecurity.allowDomain()メソッドの処理が必要となります。

30
31
32
33
34
35
				function(event:Event):void
				{
					avatar = loader.content; // avatar1.swfだとここでエラー
					addChild(avatar);
					avatar.play();
				}

URLLoaderを使う

以下をドキュメントクラスとするswfをfla.laドメインへ配置するとします。URLLoaderを使う場合はavatar1.swfでもavatar2.swfでもロードした後に、アニメーションを開始することが可能です。
但し、http://asmple.com/crossdomain.xmlにて以下の記述が必要となります。

<?xml version="1.0"?>
<!DOCTYPE cross-domain-policy SYSTEM "http://www.adobe.com/xml/dtds/cross-domain-policy.dtd">
<cross-domain-policy>
<site-control permitted-cross-domain-policies="master-only"/>
<allow-access-from domain="fla.la" />
</cross-domain-policy>
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
package  
{
	import flash.display.Loader;
	import flash.display.Sprite;
	import flash.events.Event;
	import flash.net.URLLoader;
	import flash.net.URLLoaderDataFormat;
	import flash.net.URLRequest;
 
	/**
	 * 外部リソースをURLLoaderでロードしてからメソッドにアクセス
	 * @author naoto koshikawa
	 */
	public class CrossScript2 extends Sprite
	{
		//----------------------------------------------------------------------
		//  methods
		//----------------------------------------------------------------------
		//------------------------------
		//  public methods
		//------------------------------
		/**
		 * constructor
		 */
		public function CrossScript2() 
		{
			var avatar:*;
 
			var loader:Loader = new Loader();
			loader.contentLoaderInfo.addEventListener(
				Event.COMPLETE, 
				function(event:Event):void
				{
					avatar = loader.content;
					addChild(avatar);
					avatar.play();
				}
			);
 
			var urlLoader:URLLoader = new URLLoader();
			urlLoader.dataFormat = URLLoaderDataFormat.BINARY;
			urlLoader.addEventListener(
				Event.COMPLETE, 
				function(event:Event):void
				{
					loader.loadBytes(urlLoader.data);
				}
			);
			urlLoader.load(new URLRequest("http://asmple.com/work/avatar1.swf"));
		}	
	}	
}

動くサンプル

別ドメインの外部リソースのメッソドにアクセスする例を紹介します。

Loaderを用いた実例

  • http://fla.la/swf/cross_script3.swf

から、先ほども紹介した

  • http://asmple.com/work/avatar1.swf
  • http://asmple.com/work/avatar2.swf

をロードします。先の例に照らし合わせると、cross_script3.swfがmain.swfでavatar1.swf, avatar2.swfがresource.swfとなります。

以上を踏まえて、以下のサンプルを触ってみて下さい。ロードするswfを選択してloadボタンをクリックするとswfがロードされます。ロードされたswfの周りに配置されたup, right, down, leftの各ボタンはswfに定義されたメソッドを実行します。

The Flash plugin is required to view this object.

実行すると分かるように、avatar1.swfをロードした後に、up, right, down, leftの各ボタンをクリックするとSecurityErrorが発生しますが、avatar2.swfではロードされたswfがアニメーションを開始します。

URLLoaderを用いた実例

まったく同じサンプルですが、LoaderではなくURLLoaderを用いて外部リソースをロードしています。

  • http://fla.la/swf/cross_script4.swf

から

  • http://asmple.com/work/avatar1.swf
  • http://asmple.com/work/avatar2.swf

をロードします。先の例に照らし合わせると、cross_script4.swfがmain.swfでavatar1.swf, avatar2.swfがresource.swfとなります。

The Flash plugin is required to view this object.

こちらの例では、avatar1.swfでもアバターの操作が出来る事と、avatar1.swf, avatar2.swfをロードする際に

  • http://asmple.com/crossdomain.xml

をリクエストしていることが確認出来ると思います。

firefoxをお使いの方は、Live HTTP Headersfirebugを使うと簡単に確認出来ます。

crossdomain.xmlを取得する様子をfirebugで確認

crossdomain.xmlを取得する様子をfirebugで確認

crossdomain.xmlのロードはキャッシュするので、ロードの確認の際にはブラウザのキャッシュをクリアしてからお試し下さい。

おまけ(wonderflの例)

wonderflに投稿したswfは同一ドメイン swf.wonderfl.net に存在するため、crossdomain.xml も allowDomain も 使わずに他の投稿をロードして使うことが出来ます。

ただし、以下のようにブログパーツとして貼り付ける場合はwonderfl.netドメインのswfファイルを利用するようなので、リソース側のswfに以下の記述が必要です。(このエントリーを書きながら気づきました)

Security.allowDomain("wonderfl.net");
ロードするswf

本エントリーの例では外部リソース resource.swfにあたります。

ロード元swf

本エントリーの例では外部リソース main.swfにあたります。

他の投稿から使うライブラリ的なswfを投稿してみんなに使ってもらうことも出来そうですね。ちなみに、

ちなみに、wonderflに投稿したswfのurlは以下のように取れます。

var swfURL:String = loaderInfo.url;

wonderflにも投稿してあります。

まとめ

別ドメインの外部リソースを扱う際には、Loaderを使うのか、URLLoaderを使うのかによって、クロススクリプティングをする際にチェックするポイントが異なります。

外部リソースのswfを扱うことで柔軟なflashアプリケーションを作成していきたいと思います。

 

Comments: 1

Leave a reply »

 
 
 

[...] これは以前、fla.la » クロススクリプティングで紹介した ロード元swfファイルのDisplayObjectツリーと、ロードしたswfファイルのDisplayObjectツリー間のイベント伝達フロー [...]

 
 
Leave a Reply
 
  (will not be published)