http://www.flashj.cn/wp/securityerror-2123.html
第一份安全沙箱的筆記。
因為安全沙箱困擾了不少人,所以是老生常談的問題。
今天下午我遇到了2123錯誤。
案發現場
某個列表flash頁面需要支援gravatar的頭像
(gravatar的跨域策略檔案位於http://www.gravatar.com/avatar/crossdomain.xml)
在載入他們提供的圖標題像時我遇到了安全沙箱衝突,錯誤資訊是:
SecurityError: Error #2123: 安全沙箱衝突:Loader.content:http://www.**********/lib.swf 不能訪問 http://www.gravatar.com/avatar/3b3be63a4c2a439b013787721dfce802.jpg?s=26&d=monsterid。未被授權訪問任何策略檔案。
at flash.display::Loader/get content()
at org.mousebomb.srcloader::SwfLoader/onLoadComplete()
一開始我以為是要Crossdomain檔案的,我加上了Security.loadPolicyFile(“http://www.gravatar.com/avatar/crossdomain.xml”); 嘗試,無效。
其實並不需要的——我只是要發布到網站後跨域讀取並顯示圖片,這在遠程網路域中,是直接允許以唯讀方式訪問視聽媒體內容的。
罪魁禍首
後來單獨寫了一個檔案,用Loader測試了一下可以正常讀取並顯示圖片的。
這樣想起來原來導致安全錯誤的原因在於我所使用的資源載入器,資源集區的最終工作單位中Loader是每次載入完成一個就把此視覺物件拋出,然後unload以便再次接受新任務。
片段代碼:
- _isFree = true;
- var _loadedData : DisplayObject = _loader.content;
- _loader.unload();
- var outEvent : SrcloaderEvent = new SrcloaderEvent(SrcloaderEvent.COMPLETE,{key:_key, type:_type, data:_loadedData});
- this.dispatchEvent(outEvent);
這樣的拋出視覺物件(錯誤出現在_loader.content這句)被 Flashplayer看作為“跨域資料處理” ,違反了唯讀許可,是不允許的。
解決方案
這部分直接換成Loader來載入顯示就行了。
針對跨域視聽媒體對象的顯示與讀取只能用Loader直接做容器。
[11.8補充]
根據我的理解,遠程網路域的映像要想進行處理(draw之類),只要伺服器上有跨域策略檔案標明允許,且loaderContext讀取了此策略檔案就可以的,但事實上,還是無法操作。
也許是對安全性原則還不夠瞭解,上次的問題雖然解決了卻沒有深入研究。
今天群裡有個兄台(pickgliss)為解決問題,提出這樣的方式繞過Loader載入來的圖片無法draw、無法操作BitmapData的問題:
先用URLLoader以二進位方式載入圖片,然後用Loader.loadBytes載入為顯示對象。
我在後面加上draw位元影像和smoothing來測試,果然可行!
注意:此方法適用於遠程伺服器上有跨域安全性原則賦予許可權,但依然無法操作顯示對象。不適用於沒有跨域安全性原則、或者策略檔案不允許的情況。
如何繞過安全錯誤例::
- package
- {
- import flash.display.Bitmap;
- import flash.display.BitmapData;
- import flash.display.DisplayObject;
- import flash.display.Loader;
- import flash.display.Sprite;
- import flash.events.Event;
- import flash.net.URLLoader;
- import flash.net.URLLoaderDataFormat;
- import flash.net.URLRequest;
- import flash.utils.ByteArray;
-
- public class Test extends Sprite
- {
- public function Test()
- {
- var req : URLRequest = newURLRequest("http://uc.discuz.net/data/avatar/001/29/18/69_avatar_middle.jpg");
- var loader : URLLoader = new URLLoader(req);
- loader.dataFormat = URLLoaderDataFormat.BINARY;
- loader.addEventListener(Event.COMPLETE, __complete);
- }
-
- private function __complete(e : Event) : void
- {
- var data : ByteArray = e.target.data;
- var loader : Loader = new Loader();
- loader.contentLoaderInfo.addEventListener(Event.COMPLETE, imageDataComplete);
- loader.loadBytes(data);
-
- }
-
- private function imageDataComplete(e : Event) : void
- {
- var dio : DisplayObject = e.target.content;
- var bmp : Bitmap = new Bitmap(new BitmapData(dio.width, dio.height),"auto",true);
- bmp.bitmapData.draw(dio);
- bmp.x = 100;
- bmp.y = 100;
- bmp.width = 50;
- bmp.height = 50;
- addChild(bmp);
- }
- }
- }