`
wgcode
  • 浏览: 591514 次
  • 性别: Icon_minigender_1
  • 来自: 广州
社区版块
存档分类
最新评论

深入理解Flash的沙箱 – Application Domains_下

阅读更多

Same Domain: Runtime Shared Libraries 相同的域:运行时共享库

把新增的定义增加到现有的应用程序域下可能是应用程序域最大的用处。因为继承只能把父域内的定义对子域共享,而合并定义到相同的应用程序域内则可以对所有使用这个域的SWF共享,包括父级和子级。

Parent Domain Adds Child Definitions
父应用程序域包括了子SWF的定义

运行时共享库(RSLs)正是运用了这种机制。RSLs是可以在运行时被加载的独立的代码库。通过RSLs,其他SWF可以共用其中的代码而不需要编译到自身,从而排除了冗余,减小了文件量,也让代码更容易维护。我们在主应用程序域中加载RSL,从而可以在整个程序中共享定义。

使用RSLs之前需要做些准备工作。首先,ActionScript编译器需要在发布SWF文件的时候知道哪些定义不需要被编译。

原生的Flash Player API定义就不需要编译。虽然每个SWF都需要用到原生的定义(Array,XML,Sprite等),但是这些定义只存在于Flash Player的可执行文件中,不需要也不会被编译到SWF文件中。编译器使用一个叫做playerglobal.swc的特殊SWC(预先编译的SWF类库)来识别原生定义。它包含了原生定义的接口,包括定义的名字和数据类型等。编译器通过它来编译SWF,而且不会把这些定义编译到最终的SWF中。

编译器还可以引用其他类似playerglobal.swc一样的SWC库。这些库作为“外部”类库,其中包含的定义只是用于编译,不会包含到SWF内部。

这里不详细讨论在编辑工具中如何进行库链接的设置。不同版本的编辑器的设置有些不同,具体方法请参考Flash文档。

虽然我们用SWCs来编译SWF,但实际上他们本身就是SWF文件,和其他被加载的SWF内容类似。在进行库编译的时候,同时生成了SWF和SWC文件。SWF用于运行时加载,而SWC在编译时用做外部库。

Compiling a Shared Library
编译器使用SWCs共享库,SWF共享库在运行时加载

另一个准备工作需要编写代码。使用外部库的时候,发布的SWF中不包含库中的定义。如果Flash Player尝试运行其中代码,就会产生核查错误,整个SWF基本上就瘫痪了。

Flash Player会在类第一次使用的时候校验其定义。如果应用程序域中不包括该定义,那么校验错误就会产生。

实际上缺少定义产生的错误有两种。校验错误是两种之中最糟的,表示类无法正常工作的灾难性失败。另一种是引用错误,当某种数据类型被引用但是却不可用的情况下发生。虽然缺失定义也会造成引用错误,但这种错误只会在已经经过核查的类内部打断代码执行的正常过程。

var instance:DoesNotExist;
// VerifyError: Error #1014: Class DoesNotExist could not be found.
// 当Flash Player校验包含该定义的类时发生校验错误
var instance:Object = new DoesNotExist();
// ReferenceError: Error #1065: Variable DoesNotExist is not defined.
// 当代码执行到这一行的时候发生引用错误

主要的区别在于校验错误与类定义有关,而引用错误与代码执行相关。在类内部的代码要执行之前,必须要先通过校验。上面的例子中instance对象声明为Object类型,校验可以正常通过(只是在执行的时候就会遇到引用错误)。

Note: Strict Mode 注意:严格模式

外部库是引用定义而不需将其编译到SWF中的一种方法。另一种方法是关闭严格模式,这将大大放宽了对变量使用的检查。对于类的使用来说,你可以引用一个不存在的类而不会引起编译器报错。你不能直接把不存在的类用作变量类型(这样做会在运行时产生校验错误),但是你可以像上面的“引用错误”例子中那样去引用。在非严格模式下,编译器也许会检测不到一些可能发生的错误,所以通常不建议用这种模式。

使用了RSLs的SWF文件必须保证先加载好RSLs,才能使用这些外部定义。我们应该在主应用程序开始执行之前用一个预加载器来加载RSLs。

下面演示了一个SWF加载包含Doughnut类的外部RSL的例子。虽然在SWF中直接引用了这个类,但是它却是编译在外部库中,并通过SWC的方式来引用的。RSL在Doughnut类第一次使用之前就被加载进来,所以不会造成校验错误。

Doughnut.as (编译为 doughnutLibrary.swc 和 doughnutLibrary.swf):

package {
	import flash.display.Sprite;
 
	public class Doughnut extends Sprite {
		public function Doughnut(){
 
			// draw a doughnut shape
			graphics.beginFill(0xFF99AA);
			graphics.drawCircle(0, 0, 50);
			graphics.drawCircle(0, 0, 25);
		}
	}
}

ShapesMain.as (Shapes.swf的主类):

package {
	import flash.display.Sprite;
 
	public class ShapesMain extends Sprite {
		public function ShapesMain(){
 
			// 虽然并没有编译到Shapes.swf中,
			// 但是我们通过doughnutLibrary.swc外部库
			// 可以获得对Doughnut类的引用
			var donut:Doughnut = new Doughnut();
			donut.x = 100;
			donut.y = 100;
			addChild(donut);
		}
	}
}

Shapes.swf (RSL loader):

var rslLoader:Loader = new Loader();
rslLoader.contentLoaderInfo.addEventListener(Event.INIT, rslInit);
 
// 把RSL中的定义加载到当前应用程序域中
var context:LoaderContext = new LoaderContext();
context.applicationDomain = ApplicationDomain.currentDomain;
 
var url:String = "doughnutLibrary.swf";
rslLoader.load(new URLRequest(url), context);
 
function rslInit(event:Event):void {
	// 只有当RSL中的定义导入到当前应用程序域以后
	// 我们才能用其中的Doughnut定义通过ShapesMain类的校验
	addChild(new ShapesMain());
}

在这个例子中,Shapes.swf是主程序,当RSL加载完毕后实例化主类ShapesMain。如果没有导入RSL中的定义,创建ShapesMain实例的时候就会因为在应用程序域中找不到对应的类而发生校验错误。

注意:Flex中的RSL

这里讨论的方法是最底层的方法,不应该用于Flex开发。Flex框架中有自己的一套RSLs处理机制,更多关于RSL在Flex中的应用,请参考Flex Runtime Shared Libraries (Flex 4)

Getting Definitions Dynamically 动态获取定义

我们可以用Application.getDefinition方法获取不在应用程序域内的定义,或者被父域覆盖的定义。这个方法返回应用程序域及其任意父域内的定义引用。在当前应用程序域内使用getDefinition方法的效果等同于全局函数getDefinitionByName

我们也可以通过SWF的LoaderInfo.applicationDomain来获得在ApplicationDomain.currentDomain以外的应用程序域。在下面的例子中我们用Loader加载了一个SWF文件,然后在加载的那个应用程序域中提取com.example.Box类的定义。

try {
	var domain:ApplicationDomain = loader.contentLoaderInfo.applicationDomain;
	var boxClass:Class = domain.getDefinition("com.example.Box") as Class;
	var boxInstance:Object = new boxClass();
}catch(err:Error){
	trace(err.message);
}

以上的例子中包含了两个知识点。首先,getDefinition方法的返回值被显式的转换为Class类型,这是因为getDefinition默认返回的是Object类型,有可能代表了除了类类型以外的其他类型(函数,命名空间,接口)。其次,这个操作应该要放在try-catch函数体内,因为如果getDefinition查找定义失败将会抛出错误。或者你也可以在使用getDefinition之前用ApplicationDomain.hasDefinition方法检测是否能够成功找到某个定义。

用动态方式去获取的定义,而不是那些在当前应用程序域(及继承的程序域内)的定义,是不能用作变量类型的。就像RSL一样,在应用程序域内找不到的类定义会在校验的时候报错。所以上面的例子中boxInstance变量声明为Object类型而不是Box类型,就是因为Box类的定义在应用程序域内不存在。

Same-definition Collisions 相同定义的冲突

有些时候可能会发生你引用的定义匹配到另外的应用程序域里的定义的交叉情况。这种情况将会产生如下强制转换类型错误:

TypeError: Error #1034: Type Coercion failed: cannot convert
	com.example::MyClass@51e1101 to com.example.MyClass.

你可以看到在不同内存空间里的定义用@符号进行了区分。虽然它们内部的代码可能是完全相同的(或不同),但是由于它们存在不同的应用程序域(或安全域)内,所以它们是两个不同的定义。

只有像Object那样的原生Flash Player定义才可以将位于不同域(甚至是跨安全域的)的定义关联起来。实际上,大多数时候声明一个跨域的变量类型的时候都需要用Object类型。

虽然我们可以用Object这种通用类型来解决定义冲突错误,实际上我们更应该合理安排应用程序域的位置来消除这种不匹配的情况。

Conclusion 总结

这篇教程包含了很多方面的信息。前半部分讨论了什么是安全域,以及它如何影响来自不同域的内容。Flash Player用这种安全沙箱机制保护用户的数据。Flash开发者应该了解并合理利用这种限制。

第二部分讨论了应用程序域——另一种用于在安全沙箱内划分ActionScript定义的沙箱类型。应用程序域的层级机制提供了在不同的SWF直接共享和重用定义的方法。

在安全域和应用程序域的概念上有很多容易犯的错误。希望这篇教程能够帮你对此有所准备。你不仅应当了解他们的运作方式,还要知道如何正确运用它们以达成你想要的效果。

译者注:

通过这篇文章的翻译,我才真正体会了翻译工作的难做。虽然平时看英文资料的速度还挺快,但是用中文详细复述一遍需要多花好几十倍的时间。在这篇教程的翻译中,我没有使用全文翻译等辅助工具,完全靠手打,一边翻译一遍领会作者的意图。感觉收获还是比单纯看一遍要来得更多一些。

本文介绍的知识相当重要,特别是从AS2时代成长起来的开发者很容易就掉进文中提到的一些陷阱。完全掌握这部分知识对设计模块架构,管理内存等方面都有很大的帮助。在此要再次感谢原作者senocular为我们带来这么精彩的教程。

分享到:
评论

相关推荐

    flash安全沙箱汇总

    在IT行业中,安全沙箱是一种重要的安全机制,尤其在Flash技术中扮演着核心角色。Flash安全沙箱的主要目的是为了限制并隔离运行的Flash内容,防止它们对用户系统造成潜在的危害。下面将详细介绍Flash安全沙箱的基本...

    flashplayer_11_plugin_debug_32bit

    标题“flashplayer_11_...总结来说,“flashplayer_11_plugin_debug_32bit”是一个专为开发和调试Flash内容设计的工具,虽然随着技术的发展,其重要性已不如从前,但对于处理旧项目或理解早期Web开发历史仍然有价值。

    用于单独开发和测试UI组件的沙箱_TypeScript_JavaScript_下载.zip

    "用于单独开发和测试UI组件的沙箱_TypeScript_JavaScript_下载.zip" 提供的正是这样一个工具,它支持使用TypeScript和JavaScript两种语言,为React UI组件的开发提供了一个安全、独立的环境。 TypeScript是...

    java ,c#,delphi 解决flash安全沙箱问题

    综上所述,处理 Flash 安全沙箱问题涉及理解沙箱模型、设置跨域策略、实现安全通信接口、管理权限、代码签名、异常处理以及遵循安全编码实践等多个方面。开发者需要在 Java, C# 和 Delphi 中综合运用这些技术来创建...

    install_flash_player_ax_30.zip

    对于仍在使用 Windows 7 或更低版本的用户,建议转而使用支持现代 web 标准的浏览器和替代技术,或者在必须使用 Flash 的情况下,采取严格的网络安全措施,例如限制浏览的网站和使用沙箱环境。同时,对于 Windows 8 ...

    要要安全沙箱(11Safe_Sandbox) v1.0.0.1.rar.cab

    backups

    install_flash_player_ppapi(无锁区)

    2. **PPAPI(Pepper Plugin API)**:是Google Chrome浏览器使用的一种插件接口,与NPAPI( Netscape Plugin Application Programming Interface)相比,PPAPI提供了更安全、更高效的环境,因为它运行在沙箱模式下,...

    深入理解ApplicationDomain和SecurityDomain

    ### 深入理解ApplicationDomain和SecurityDomain #### 安全域(Security Domain)与应用程序域(Application Domain)概述 安全域与应用程序域是Flash Player中两种重要的沙箱概念,它们帮助开发者理解如何管理和...

    flash 安全沙箱处理集合

    通过以上内容,你应该对AS3中的安全沙箱有了更深入的理解。如果你在实际项目中遇到沙箱问题,可以参考提供的文件集合,寻找解决方案。这些资料很可能包含了多种处理方法,以应对各种情况。记住,解决这类问题可能...

    Flash Socket安全沙箱策略mini服务器,解决Flash Socket安全沙箱,安全策略

    本程序为绿色mini服务程序 程序会自动打开Flash默认的843端 自动将crossdomain.xml返回给flash客户端 您可以修改crossdomain.xml中的内容,大小不要超过10K 有问题可email我

    火狐浏览器崩溃怎么办,Flash沙箱安全模式帮你轻松解决.docx

    总之,理解并正确应用Flash沙箱安全模式是解决火狐浏览器崩溃问题的一种策略,但这并不是万能的。根据具体情况,可能还需要结合其他故障排查方法,如排查硬件加速问题、内存管理等,以确保最佳的浏览器性能和稳定性...

    ApplicationDomain的误解,安全沙箱有关内容

    ### ApplicationDomain的理解与安全沙箱相关知识 #### 一、ApplicationDomain的概念与作用 在Adobe Flash AS3编程中,`ApplicationDomain`是一个重要的概念,它主要用于管理类的加载和访问控制,同时也为运行时...

    Flash加载swf文件的沙箱问题

    本篇文章将详细探讨“Flash加载SWF文件的沙箱问题”,并结合标签“源码”和“工具”来深入理解这个问题。 Flash Player为了确保用户的安全,采用了沙箱模型,这个模型将不同的运行环境分隔开来,防止恶意代码对用户...

    沙箱原理介绍,沙箱的分类

    沙箱技术是一种重要的网络安全防御手段,它通过创建一个隔离的环境来执行可能包含恶意代码的文件或应用程序,以便在不损害真实系统的情况下检测潜在的威胁。沙箱的基本原理是利用虚拟化技术,使得受控的代码在一个...

    as3 安全沙箱 处理办法

    1. **本地沙箱**:当Flash内容从用户的本地硬盘加载时,它们运行在本地沙箱中,不能访问网络资源,但可以访问本地文件系统和硬件。 2. **网络沙箱**:如果内容从网络上加载,如通过HTTP或FTP,它们将运行在网络沙箱...

    全面认识Flex安全沙箱

    在理解Flex安全沙箱时,还需要考虑FlashPlayer的权限控制,它由四个层次组成: - **管理用户控制**:系统管理员可以通过mms.cfg文件和全局FlashPlayer信任目录来设定全局安全策略。 - **用户控制**:普通用户可以...

    flash读取txt变量附_带源文件

    本主题将深入探讨如何在Flash中使用ActionScript(AS)来读取.txt文件中的变量。 一、ActionScript简介 ActionScript是Adobe Flash Professional和Flex的主要编程语言,用于创建交互式内容、游戏和应用程序。AS3是...

    Flash Socket策略mini服务器,迅速解决Flash socket安全策略问题,安全沙箱问题

    本程序为绿色mini服务程序 程序会自动打开Flash默认的843端口 自动将crossdomain.xml返回给flash客户端 您可以修改crossdomain.xml中的内容,大小不要超过10K

Global site tag (gtag.js) - Google Analytics