Выполнение сценариев между содержимым из различных доменов

Adobe AIR 1.0 и более новых версий

При установке приложений AIR они наделяются особыми привилегиями. Очень важно, чтобы эти привилегии не были предоставлены другому содержимому, в том числе удаленным файлам и локальным файлам, которые не являются частью приложения.

О мосте изолированной программной среды в AIR

Как правило, содержимое из одних доменов не может выполнять сценарии в других доменах. Для защиты приложений AIR от случайной утечки конфиденциальной информации или перехвата управления на содержимое в изолированной программной среде application (содержимое, установленное с приложением) накладываются следующие ограничения:

  • Код в изолированной программной среде приложения не может предоставить доступ другим изолированным средам путем вызова метода Security.allowDomain(). При вызове этого метода из защищенной изолированной программной среды приложения происходит ошибка.

  • Импорт непрограммного содержимого в изолированную программную среду приложения путем задания свойства LoaderContext.securityDomain или LoaderContext.applicationDomain запрещен.

Бывают случаи, когда главному приложению AIR требуется, чтобы содержимое с удаленного домена имело управляемый доступ к сценариям в главном приложении AIR, или наоборот. Для этого среда выполнения создает мост изолированной программной среды, который служит шлюзом между двумя изолированными программными средами. Мост изолированной программной среды обеспечивает открытое взаимодействие между изолированной программной средой remote и изолированной программной средой приложения.

Мост изолированной программной среды предоставляет два объекта, доступ к которым имеет и загруженный, и загружаемый сценарий.

  • Объект parentSandboxBridge позволяет загружаемому содержимому предоставить сценариям загруженного содержимого доступ к свойствам и функциям.

  • Объект childSandboxBridge позволяет загруженному содержимому предоставить сценариям загружаемого содержимого доступ к свойствам и функциям.

Объекты, доступ к которым предоставлен при помощи моста изолированной программной среды, передаются по значению, а не по ссылке. Все данные сериализуются. Это значит, что объекты, предоставленные одной стороной моста, не могут быть заданы другой стороной, и что все предоставленные объекты нетипизированные. Более того, предоставлять доступ можно только к простым объектам и функциям, а не к сложным.

Если дочернее содержимое пытается задать свойство объекта parentSandboxBridge, среда выполнения выдает исключение SecurityError. Таким же образом, если родительское содержимое пытается задать свойство объекта childSandboxBridge, среда выполнения выдает исключение SecurityError.

Пример моста изолированной программной среды (SWF)

Предположим, приложение AIR «музыкальный магазин» хочет разрешить удаленным SWF-файлам сообщать стоимость альбомов, но чтобы удаленный SWF-файл не сообщал о том, что это распродажная цена. Для этого класс StoreAPI предоставляет метод для получения цены, но скрывает распродажную цену. Экземпляр этого класса StoreAPI затем присваивается свойству parentSandboxBridge объекта LoaderInfo объекта Loader, который загружает удаленный SWF.

Ниже приводится код для музыкального магазина 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();     
    } 
}

Следующий код является примером SWF-файла PriceQuoter, который сообщает данные о магазинной цене, но не может сообщить о распродажной цене:

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 дочернего документа. Пример задания функций моста в содержимом HTML см. в разделе Настройка интерфейса моста изолированной программной среды.

Ограничение доступа к API-интерфейсу

При создании моста изолированной программной среды важно предоставлять доступ к API-интерфейсам высокого уровня, которые ограничивают степень их возможного неправомочного использования. Имейте в виду, что содержимое, вызывающее функцию моста, может быть подвержено риску (например, за счет ввода кода). Так, например, предоставление доступа к методу readFile(path:String) (который считывает содержимое произвольного файла) через мост может привести к его неправомочному использованию. В этом случае лучше предоставить доступ к API-интерфейсу readApplicationSetting(), который не использует путь и считывает конкретный файл. Более семантический подход снижает вред, который может причинить приложение в случае, если одна из его частей подвергается риску.