在不同網域中的內容之間編寫指令碼

Adobe AIR 1.0 以及更新的版本

AIR 應用程式會在安裝時授予特殊權限。有一點很重要,絕對不能讓相同的權限洩漏給其它內容,包括不屬應用程式的遠端檔案和本機檔案。

關於 AIR 安全執行程序橋接

在正常情況下,網域的內容無法呼叫位於其它網域的指令碼。為了避免 AIR 應用程式遇到權限資訊或控制意外洩漏的情況, application (應用程式) 安全執行程序中內容 (與應用程式一起安裝的內容) 上設了下列限制:

  • 應用程式安全執行程序中的程式碼無法透過呼叫 Security.allowDomain() 方法,在其它安全執行程序中受到許可。從應用程式安全執行程序呼叫這個方法將會擲出錯誤。

  • 禁止透過設定 LoaderContext.securityDomain LoaderContext.applicationDomain 屬性,將非應用程式內容匯入至應用程式安全執行程序。

不過,在某些情況下,主 AIR 應用程式需要來自遠端網域的內容,以控制主 AIR 應用程式中指令碼的存取,或反之亦然。為了完成上述作業,執行階段提供「安全執行程序橋接」機制,可做為兩個安全執行程序之間的閘道。安全執行程序橋接可以提供遠端與應用程式安全執行程序之間的明確互動。

安全執行程序橋接會公開兩個物件,供被載入端和載入端指令碼存取:

  • parentSandboxBridge 物件可以讓載入的內容將屬性和函數公開給被載入內容中的指令碼。

  • childSandboxBridge 物件可以讓被載入的內容將屬性和函數公開給載入內容中的指令碼。

經由安全執行程序橋接公開的物件是由值傳遞,而非由參考傳遞。所有資料都已序列化。也就是說,由橋接一端公開的物件不能由另一端設定,而被公開的物件都是不具類型的。而且,您也只能公開簡單物件和函數,而不能公開複雜的物件。

如果子內容嘗試將某個物件設定為 parentSandboxBridge 物件,執行階段就會擲出 SecurityError 例外。同樣地,如果父內容嘗試將某個物件設定為 childSandboxBridge 物件,執行階段也會擲出 SecurityError 例外。

安全執行程序橋接範例 (SWF)

假設 AIR 音樂商店應用程式要允許遠端 SWF 檔廣播專集的價格,但不希望遠端 SWF 檔洩漏此價格是否為售價。為了執行這項作業,StoreAPI 類別提供了方法,可取得價格,但掩飾售價。然後,此 StoreAPI 類別的實體會指定給載入遠端 SWF 之 Loader 物件的 LoaderInfo 物件之 parentSandboxBridge 屬性。

下列是該 AIR 音樂商店的程式碼:

<?xml version="1.0" encoding="utf-8"?> 
<mx:WindowedApplication xmlns:mx="http://www.adobe.com/2006/mxml" layout="absolute" title="Music Store" creationComplete="initApp()"> 
    <mx:Script> 
        import flash.display.Loader; 
        import flash.net.URLRequest; 
     
        private var child:Loader; 
        private var isSale:Boolean = false; 
         
        private function initApp():void { 
            var request:URLRequest =  
                    new URLRequest("http://[www.yourdomain.com]/PriceQuoter.swf") 
 
            child = new Loader(); 
            child.contentLoaderInfo.parentSandboxBridge = new StoreAPI(this); 
            child.load(request); 
            container.addChild(child); 
        } 
        public function getRegularAlbumPrice():String { 
            return "$11.99"; 
        } 
        public function getSaleAlbumPrice():String { 
            return "$9.99"; 
        } 
        public function getAlbumPrice():String { 
            if(isSale) { 
                return getSaleAlbumPrice(); 
            } 
            else { 
                return getRegularAlbumPrice();     
            } 
        } 
    </mx:Script> 
    <mx:UIComponent id="container" /> 
</mx:WindowedApplication> 

StoreAPI 物件呼叫主應用程式,以擷取一般專集價格,但在呼叫 getSaleAlbumPrice() 方法時,傳回「無法使用」。下列程式碼會定義 StoreAPI 類別:

public class StoreAPI 
{ 
    private static var musicStore:Object; 
     
    public function StoreAPI(musicStore:Object) 
    { 
        this.musicStore = musicStore; 
    } 
 
    public function getRegularAlbumPrice():String { 
        return musicStore.getRegularAlbumPrice(); 
    } 
     
    public function getSaleAlbumPrice():String { 
        return "Not available"; 
    } 
     
    public function getAlbumPrice():String { 
        return musicStore.getRegularAlbumPrice();     
    } 
}

下列程式碼代表報告商店價格、但不會報告銷售價格的 PriceQuoter SWF 檔之範例:

package 
{ 
    import flash.display.Sprite; 
    import flash.system.Security; 
    import flash.text.*; 
     
    public class PriceQuoter extends Sprite 
    { 
        private var storeRequester:Object; 
         
        public function PriceQuoter() { 
            trace("Initializing child SWF"); 
            trace("Child sandbox: " + Security.sandboxType); 
            storeRequester = loaderInfo.parentSandboxBridge; 
             
            var tf:TextField = new TextField(); 
            tf.autoSize = TextFieldAutoSize.LEFT; 
            addChild(tf); 
             
            tf.appendText("Store price of album is: " + storeRequester.getAlbumPrice()); 
            tf.appendText("\n"); 
            tf.appendText("Sale price of album is: " + storeRequester.getSaleAlbumPrice()); 
        } 
    } 
}

安全執行程序橋接範例 (HTML)

在 HTML 內容中, parentSandboxBridge childSandboxBridge 屬性會加入至子文件的 JavaScript window 物件。如需如何在 HTML 內容中設定橋接函數的範例,請參閱 設定安全執行程序橋接介面

限制 API 公開

公開安全執行程序橋接時,務必要公開定義可濫用程度的高階 API。請記住,呼叫您橋接實作的內容可能會遭受危害 (例如,經由程式碼插入)。舉例來說,經由橋接公開 readFile(path:String) 方法 (可讀取任意檔案的內容) 便是可能會被濫用的弱點。較為適當的做法是公開不接受路徑且會讀取特定檔案的 readApplicationSetting() API。較具語意的手法會在部分應用程式遭到危害時,限制應用程式可能會造成的損害。