Script entre conteúdos em domínios distintos

Adobe AIR 1.0 e posterior

Aplicativos AIR recebem privilégios especiais quando são instalados. É fundamental que os mesmos privilégios não vazem para outro conteúdo, incluindo arquivos remotos e arquivos locais que não fazem parte do aplicativo.

Sobre a ponte de caixa de proteção do AIR

Normalmente, o conteúdo de outros domínios não pode chamar scripts de outros domínios. Para proteger os aplicativos AIR de vazamentos acidentais de informações privilegiadas ou de controle, as restrições a seguir são colocadas no conteúdo na caixa de proteção de segurança do aplicativo (conteúdo instalado com o aplicativo):

  • O código na caixa de proteção de segurança do aplicativo não pode permitir que outras caixas de proteção chamem o método Security.allowDomain() . Chamar esse método de uma caixa de proteção de segurança do aplicativo gerará um erro.

  • Evita-se importar conteúdo "não aplicativo" da caixa de proteção do aplicativo, definindo a propriedade LoaderContext.securityDomain ou LoaderContext.applicationDomain .

Ainda há casos em que o aplicativo principal do AIR requer que o conteúdo de um domínio remoto tenha acesso controlado a scripts no aplicativo principal do AIR ou vice-versa. Para fazer isso, o tempo de execução oferece o mecanismo ponte de caixa de proteção , que serve como gateway entre as duas caixas de proteção. A ponte de caixa de proteção pode oferecer interação explícita entre as caixas de proteção de segurança do aplicativo e remota.

A ponte de caixa de proteção expõe dois objetos que os scripts, carregados e em carregamento, podem acessar:

  • O objeto parentSandboxBridge permite carregar propriedades e funções de exposição de conteúdo para scripts no conteúdo carregado.

  • O objeto childSandboxBridge permite que o conteúdo carregado exponha propriedades e funções para scripts no conteúdo que está em carregamento.

Os objetos expostos através da ponte de caixa de proteção são passadas por valor e não por referência. Todos os dados são serializados. Isso significa que os objetos expostos de um lado da ponte não podem ser definidos pelo outro lado da ponte e que os objetos expostos são todos sem categoria. Além disso, você pode expor objetos e funções simples, você não pode expor objetos complexos.

Se o conteúdo filho tentar definir um objeto para o objeto parentSandboxBridge, o tempo de execução lançará uma exceção SecurityError. Da mesma forma, se o conteúdo pai tentar definir um objeto para o objeto childSandboxBridge, o tempo de execução lançará uma exceção SecurityError.

Exemplo de ponte de caixa de proteção (SWF)

Suponhamos que um aplicativo de armazenamento de música do AIR deseja permitir que arquivos remotos SWF transmitam preços de álbuns, mas não deseja que o arquivo remoto SWF divulgue se é preço de venda. Para fazer isso, a classe StoreAPI oferece um método para adquirir o preço, mas ocultar o preço de venda. Em seguida, é atribuída uma ocorrência dessa classe StoreAPI à propriedade parentSandboxBridge do objeto LoaderInfo do objeto Loader que carrega o SWF remoto.

A seguir está o código para armazenamento de música do 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> 

O objeto StoreAPI chama o aplicativo principal para recuperar o preço regular do álbum, mas retorna "Não disponível" quando o método getSaleAlbumPrice() é chamado. O código a seguir define a classe 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();     
    } 
}

O seguinte código representa um exemplo de um arquivo PriceQuoter SWF que informa o preço da loja, mas não pode informar o preço de venda:

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()); 
        } 
    } 
}

Exemplo de ponte de caixa de proteção (HTML)

No conteúdo HTML, as propriedades parentSandboxBridge e childSandboxBridge são adicionados ao objeto de janela de JavaScript de um documento filho. Para obter um exemplo sobre como definir funções de ponte em conteúdo HTML, consulte Configuração de interface de ponte de caixa de proteção .

Limitação de exposição de API

Ao expor pontes de caixa de proteção, é importante expor APIs de alto nível que limitem o grau em que podem ser abusadas. Lembre-se de que o conteúdo que chama a implementação da ponte pode estar comprometido (por exemplo, através de uma injeção de código). Portanto, por exemplo, expor um método readFile(path:String) (que lê o conteúdo de um arquivo arbitrário) através de uma ponte, estará vulnerável a abusos. Talvez seja melhor expor uma API readApplicationSetting() que não siga um caminho e leia um arquivo específico. A abordagem mais semântica limita o dano que o aplicativo pode causar, já que parte dele está comprometida.