通过脚本访问不同域中的内容Adobe AIR 1.0 和更高版本 AIR 应用程序在安装时会被授予特殊权限。不要将相同权限泄露给其他内容(包括不属于应用程序的远程文件和本地文件),这一点很重要。 关于 AIR 沙箱桥通常,一个域中的内容无法调用其他域中的脚本。为了保护 AIR 应用程序不会意外泄露获得权限的信息或控制,对应用程序安全沙箱中的内容(随应用程序一起安装的内容)施加了以下限制:
但是仍存在这样一些情况:主 AIR 应用程序要求远程域中的内容对主 AIR 应用程序中的脚本具有受控访问权限,反之亦然。为此,运行时提供了沙箱桥机制,沙箱桥充当两个沙箱之间的通道。沙箱桥可以在远程安全沙箱和应用程序安全沙箱之间提供显式交互。 沙箱桥公开了以下两个对象,已加载和要加载的脚本都可以访问这两个对象:
通过沙箱桥公开的对象按值而不是按引用进行传递。所有数据都会序列化。这意味着由桥的一端公开的对象无法由另一端设置,并且公开的对象为无类型对象。此外,只能公开简单对象和函数;不能公开复杂对象。 如果子级内容尝试设置 parentSandboxBridge 对象的属性,则运行时会引发 SecurityError 异常。同样,如果父级内容尝试设置 childSandboxBridge 对象的属性,则运行时也会引发 SecurityError 异常。 沙箱桥示例 (SWF)假设 AIR 音乐商店应用程序需要允许远程 SWF 文件广播专辑价格,但不需要远程 SWF 文件透露该价格是否为销售价格。为此,StoreAPI 类提供了一种获取价格的方法,但屏蔽了销售价格。随后会将此 StoreAPI 类的实例分配给 Loader 对象(该对象加载远程 SWF)的 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() 方法时将返回“Not available”。以下代码定义了 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。一旦应用程序部分受到损坏,语义方法越多,就越能限制应用程序产生的破坏。 |
|