跨脚本访问

Flash Player 9 和更高版本,Adobe AIR 1.0 和更高版本

如果使用 ActionScript 3.0 编写的两个 SWF 文件或在 AIR 中运行的两个 HTML 文件来自同一域(例如,一个 SWF 文件的 URL 是 http://www.example.com/swfA.swf,另一个的是 http://www.example.com/swfB.swf),则在其中一个文件中定义的代码可检查并修改另一个文件中的变量、对象、属性、方法等,反之亦然。这称为“跨脚本访问”。

如果这两个文件来自不同的域(例如,http://siteA.com/swfA.swf 和 http://siteB.com/swfB.swf),那么,在默认情况下,Flash Player 和 AIR 不允许 swfA.swf 编写 swfB.swf 的脚本,也不允许 swfB.swf 编写 swfA.swf 的脚本。通过调用 Security.allowDomain() ,一个 SWF 文件可授予其他域中的 SWF 文件编写其脚本的权限。通过调用 Security.allowDomain("siteA.com") ,swfB.swf 向来自 siteA.com 的 SWF 文件授予访问其脚本的权限。

在 AVM1 SWF 文件和 AVM2 SWF 文件之间不支持跨脚本访问。AVM1 SWF 文件是使用 ActionScript 1.0 或 ActionScript 2.0 创建的文件。(AVM1 和 AVM2 指的是 ActionScript 虚拟机。)但是,可以使用 LocalConnection 类在 AVM1 和 AVM2 之间发送数据。

在任何跨域的情况下,明确所涉及的双方非常重要。为了便于进行此讨论,我们将执行跨脚本访问的一方称为“访问方”(通常是执行访问的 SWF),将另一方称为“被访问方”(通常是被访问的 SWF)。当 siteA.swf 访问 siteB.swf 的脚本时,siteA.swf 是访问方,siteB.swf 是被访问方,如下图所示:

使用 Security.allowDomain() 方法建立的跨域权限是不对称的。在上例中,siteA.swf 可以访问 siteB.swf 的脚本,但 siteB.swf 无法访问 siteA.swf 的脚本,这是因为 siteA.swf 未调用 Security.allowDomain() 方法来授予 siteB.com 中的 SWF 文件访问其脚本的权限。可以通过使两个 SWF 文件都调用 Security.allowDomain() 方法来设置对称权限。

除了防止 SWF 文件受到其他 SWF 文件发起的跨域脚本编写外,Flash Player 还防止 SWF 文件受到 HTML 文件发起的跨域脚本编写。可以通过 ExternalInterface.addCallback() 方法建立的回调执行 HTML 到 SWF 的脚本访问。当 HTML 到 SWF 的脚本访问跨域时,被访问的 SWF 文件必须调用 Security.allowDomain() 方法(这与访问方是 SWF 文件时一样),否则操作将失败。有关详细信息,请参阅 作者(开发人员)控制

此外,Flash Player 还对 SWF 到 HTML 的脚本访问提供安全控制。有关详细信息,请参阅 控制外出 URL 访问

Stage 安全性

Stage 对象的某些属性和方法可用于显示列表中的任何 sprite 或影片剪辑。

但是,我们说 Stage 对象有一个所有者,即加载的第一个 SWF 文件。默认情况下,Stage 对象的以下属性和方法只能用于与舞台所有者位于同一安全沙箱中的 SWF 文件:

属性

方法

align

addChild()

displayState

addChildAt()

frameRate

addEventListener()

height

dispatchEvent()

mouseChildren

hasEventListener()

numChildren

setChildIndex()

quality

willTrigger()

scaleMode

showDefaultContextMenu

stageFocusRect

stageHeight

stageWidth

tabChildren

textSnapshot

width

为使与 Stage 所有者不在同一沙箱中的 SWF 文件能够访问这些属性和方法,舞台所有者 SWF 文件必须调用 Security.allowDomain() 方法来允许外部沙箱的域。有关详细信息,请参阅 作者(开发人员)控制

frameRate 属性是一种特殊情况:任何 SWF 文件均能读取 frameRate 属性。但是,只有位于 Stage 所有者的安全沙箱中的文件(或通过调用 Security.allowDomain() 方法被授予权限的文件)才能更改该属性。

此外,对于 Stage 对象的 removeChildAt() swapChildrenAt() 方法还存在一些限制,但是这些限制与其他限制不同。要调用这些方法,不需要与 Stage 所有者位于同一域中,而是代码必须与受影响的子对象位于同一域中,或者子对象可以调用 Security.allowDomain() 方法。

遍历显示列表

一个 SWF 文件能够访问从其他沙箱中加载的显示对象受到一定限制。为使 SWF 文件能够访问由其他沙箱中的另一个 SWF 文件创建的显示对象,被访问的 SWF 文件必须调用 Security.allowDomain() 方法向进行访问的 SWF 文件所在的域授予访问权限。有关详细信息,请参阅 作者(开发人员)控制

要访问由 Loader 对象加载的 Bitmap 对象,图像文件的原始服务器上必须存在 URL 策略文件,并且该 URL 策略文件必须为尝试访问该 Bitmap 对象的 SWF 文件所在的域授予访问权限(请参阅 网站控制(策略文件) )。

与加载的文件(和 Loader 对象)相对应的 LoaderInfo 对象包括以下三种属性(定义加载的对象和 Loader 对象之间的关系): childAllowsParent parentAllowsChild sameDomain

事件安全性

根据调度事件的显示对象所在的沙箱,与显示列表相关的事件具有一定的安全性访问限制。显示列表中的事件具有冒泡阶段和捕获阶段(在 处理事件 中介绍)。在冒泡阶段和捕获阶段期间,事件从源显示对象开始迁移,并经过显示列表中的父显示对象。如果父对象与源显示对象位于不同的安全沙箱中,则捕获阶段和冒泡阶段在父对象的下方停止,除非父对象的所有者与源对象的所有者互相信任。这种互相信任可以通过以下方式来建立:

  1. 拥有父对象的 SWF 文件必须调用 Security.allowDomain() 方法,以信任拥有源对象的 SWF 文件所在的域。

  2. 拥有源对象的 SWF 文件必须调用 Security.allowDomain() 方法,以信任拥有父对象的 SWF 文件所在的域。

与加载的文件(和 Loader 对象)相对应的 LoaderInfo 对象包括以下两种属性(定义加载的对象和 Loader 对象之间的关系): childAllowsParent parentAllowsChild

对于从显示对象以外的对象调度的事件,不存在任何安全检查或与安全相关的含义。