mashup 是一個(gè) Web 應(yīng)用程序,它集成了來(lái)自多個(gè)源的內(nèi)容并將其交付到一個(gè)頁(yè)面中進(jìn)行顯示。服務(wù)器向每個(gè)內(nèi)容源發(fā)出請(qǐng)求,解析收到的信息,并將結(jié)果綜合到一個(gè)頁(yè)面中發(fā)給瀏覽器,如 圖 1 所示。
Asynchronous JavaScript + XML(Ajax)應(yīng)用程序 使 Web 頁(yè)面能從服務(wù)器獲取內(nèi)容并使用 JavaScript™ 代碼異步地在適當(dāng)位置進(jìn)行自我更新,如 圖 2 所示。這樣,用戶就可以與富用戶界面 (UI) 進(jìn)行交互而無(wú)需重新加載整個(gè)頁(yè)面。服務(wù)器向?yàn)g覽器發(fā)送初始頁(yè)面,后者回調(diào)服務(wù)器以獲取更新后的內(nèi)容。異步的 JavaScript 代碼調(diào)用頻繁使用 XML 來(lái)編碼數(shù)據(jù);但是,其他的數(shù)據(jù)格式則更通用,如 JavaScript Object Notation (JSON)、HTML 和分隔文本。
Ajax mashup 是一種混合的 Web 應(yīng)用程序。它使用 Ajax 技術(shù)來(lái)顯示富 UI,此類(lèi)富 UI 使用從多個(gè)源異步檢索到的內(nèi)容在適當(dāng)位置進(jìn)行自我更新。服務(wù)器向?yàn)g覽器發(fā)送初始頁(yè)面,后者發(fā)出調(diào)用以檢索更新后的內(nèi)容。這些調(diào)用可從瀏覽器直接發(fā)往第三方源或者發(fā)回初始服務(wù)器,初始服務(wù)器用作第三方內(nèi)容的代理。
![]() ![]() |
![]()
|
當(dāng)設(shè)計(jì)包含當(dāng)前瀏覽器環(huán)境的元素時(shí),沒(méi)有人注意到 Ajax mashup。瀏覽器、超文本傳輸協(xié)議(HTTP)或 HTML 或?qū)iT(mén)設(shè)計(jì)用于容納瀏覽器的(以一種安全而健壯的方式)異步檢索多個(gè)源中內(nèi)容的功能的 XHTML 都沒(méi)有內(nèi)置任何組件。World Wide Web Consortium (W3C) HTTP 規(guī)范中的一些可能用于 mashup 的一些特性(如 Document Object Model (DOM) Level 3 Load 和 Save Specification)并未由大多數(shù)瀏覽器完全實(shí)現(xiàn),或是根本沒(méi)有實(shí)現(xiàn)。
Dynamic HTML (DHTML) 開(kāi)始時(shí)不與動(dòng)態(tài)檢索到的內(nèi)容結(jié)合使用。動(dòng)態(tài) Web 頁(yè)面的顯示和數(shù)據(jù)元素都與操作它們的腳本一起交付。這些腳本將顯示、隱藏、移動(dòng)、創(chuàng)建和銷(xiāo)毀文檔對(duì)象以便實(shí)現(xiàn)動(dòng)態(tài)效果,但是一旦需要從服務(wù)器獲取更多數(shù)據(jù),原頁(yè)面就被新頁(yè)面取代。數(shù)據(jù)流與頁(yè)面重新加載同步。
因此,希望構(gòu)建混合 Web 應(yīng)用程序(現(xiàn)在稱(chēng)為 mashup)的開(kāi)發(fā)人員必須利用可用的技術(shù)設(shè)法對(duì)其進(jìn)行擴(kuò)展以滿足他們的需求。有兩種方法可使瀏覽器在無(wú)需重新加載頁(yè)面的情況下檢索內(nèi)容:嵌入外部傳輸機(jī)制和使用瀏覽器本地對(duì)象執(zhí)行傳輸任務(wù)。
早期的解決方案是 Microsoft 的 Remote Scripting,它使用一個(gè) Java™ applet 與服務(wù)器端組件交換 XML 格式的消息。此方法很快就因?yàn)楣?yīng)商的爭(zhēng)論以及 Java Virtual Machine (JVM) 和安全模型的差異而變得不實(shí)用。
Microsoft 稍后構(gòu)建了 XMLHttpRequest
(XHR) 對(duì)象,其設(shè)計(jì)者的預(yù)想是只能通過(guò) Microsoft® Outlook® Web Access (OWA) 來(lái)使用該對(duì)象。該對(duì)象最初只能由 Windows® Internet Explorer® 用戶使用,直到多年后 Mozilla 和 Safari 采用它時(shí),才得到廣泛使用。它最初是一個(gè)外部的 Microsoft ActiveX® 對(duì)象,而當(dāng)前的實(shí)現(xiàn)則是瀏覽器內(nèi)的本地對(duì)象。雖然其名稱(chēng)為 XHR,但是 XHR 對(duì)象卻可以傳輸任意格式的數(shù)據(jù)而非僅限于有效的 XML 格式數(shù)據(jù)。
很多開(kāi)發(fā)人員使用 Macromedia Flash 的 XML 通信特性來(lái)構(gòu)建可嵌入的組件與服務(wù)器進(jìn)行通信。XMLSocket
和 flex.net.socket
對(duì)象提供了類(lèi)似 XHR 的功能,但附帶了額外的通信控制和 XML 解析功能。
由于外部傳輸機(jī)制相關(guān)的問(wèn)題和依賴(lài)性,互聯(lián)網(wǎng)開(kāi)發(fā)團(tuán)體協(xié)作發(fā)現(xiàn)并開(kāi)發(fā)了幾個(gè)瀏覽器本地的遠(yuǎn)程調(diào)用方法。
iframe
元素來(lái)加載外部?jī)?nèi)容:然后通過(guò) DOM 訪問(wèn) iframe
,提取加載文檔中的內(nèi)容。您可指定 URL querystring
中的任何參數(shù)或動(dòng)態(tài)創(chuàng)建一個(gè)表單,此表單以 iframe
為目標(biāo)提交到服務(wù)。此方法與很大范圍內(nèi)的當(dāng)前的和舊式瀏覽器兼容。 img
元素發(fā)送內(nèi)容請(qǐng)求:服務(wù)器使用 URL 的 querystring
中的參數(shù)執(zhí)行其任務(wù),然后在 cookie 中返回編碼后的內(nèi)容。此方法僅限于可輕松通信數(shù)量的數(shù)據(jù)使用,因?yàn)?querystring
和 cookie 都有大小限制。 querystring
中的參數(shù)。 請(qǐng)參閱 參考資料 中關(guān)于這些工具和技術(shù)的詳細(xì)信息的鏈接。
![]() ![]() |
![]()
|
大多數(shù)可用于異步檢索內(nèi)容的技術(shù)都繼承了 JavaScript 安全模型的安全性,它使腳本只與源于該腳本所屬頁(yè)面所在的同一服務(wù)器的元素進(jìn)行交互。這就是所有瀏覽器都實(shí)現(xiàn)了的同源策略(Same Origin Policy)。
要讓 Web 頁(yè)面從第三方檢索內(nèi)容,必須避開(kāi)同源策略。常用的不受同源策略限制的例外是 <script>
標(biāo)記技術(shù),由此向頁(yè)面的 DOM 追加 <script>
元素,致使其加載并運(yùn)行元素的 src
屬性所指定的 URL 處發(fā)現(xiàn)的代碼。
使用 <script>
標(biāo)記運(yùn)行來(lái)自多個(gè)站點(diǎn)的腳本以所有相關(guān)站點(diǎn)間的高水平信任為前提,因?yàn)樗写祟?lèi)腳本都在相同的執(zhí)行和安全上下文中運(yùn)行,因此可能獲得其他站點(diǎn)的信息和 cookie 的訪問(wèn)權(quán)。
![]() ![]() |
![]()
|
當(dāng)前廣泛用于啟用 Ajax mashup 的工作區(qū)都會(huì)產(chǎn)生一些代價(jià)。當(dāng)擴(kuò)展瀏覽器的設(shè)計(jì)限制時(shí),就會(huì)影響應(yīng)用程序總體操作的其他方面。這種做法通常會(huì)導(dǎo)致應(yīng)用程序的安全性或可伸縮性降低。
當(dāng)受到瀏覽器的同源策略限制時(shí),承載應(yīng)用程序的服務(wù)器必須承擔(dān)獲取第三方內(nèi)容并將其發(fā)送到客戶機(jī)的任務(wù)。服務(wù)器除提供常規(guī)的服務(wù)器功能外,還擔(dān)當(dāng)?shù)谌椒?wù)的客戶機(jī)的角色。
使用服務(wù)器作為每個(gè)客戶機(jī)事務(wù)的代理意味著大量用戶可能導(dǎo)致過(guò)度的服務(wù)器負(fù)載。使用此技術(shù)的應(yīng)用程序需要設(shè)計(jì)成服務(wù)器端可伸縮,使用多個(gè)同等的服務(wù)器處理請(qǐng)求負(fù)載。
使用 <script>
標(biāo)記避開(kāi)同源策略使客戶機(jī)能檢索來(lái)自第三方的內(nèi)容。 此功能消除了服務(wù)器的可伸縮性瓶頸,因?yàn)槊總€(gè)額外的客戶機(jī)都承擔(dān)了自身的內(nèi)容收集任務(wù)。
<script>
標(biāo)記的可伸縮性?xún)?yōu)點(diǎn)的獲得以避開(kāi)同源策略安全性模型為代價(jià),可能導(dǎo)致易于收到攻擊:
![]() ![]() |
![]()
|
很明顯,瀏覽器當(dāng)前提供的用于 mashup 的工具不能構(gòu)建同時(shí)具有可伸縮性和安全性的應(yīng)用程序。開(kāi)發(fā)人員必須找到從當(dāng)前和長(zhǎng)遠(yuǎn)角度來(lái)看都有效的解決方案。
一種最近開(kāi)發(fā)的內(nèi)容檢索技術(shù)通過(guò)其 src
URL 的片段標(biāo)識(shí)符(URL 中 # 符號(hào)后的部分)使用了頁(yè)面腳本和隱藏的 iframe
之間的通信。父頁(yè)面中的腳本和嵌入的 iframe
可設(shè)置彼此的片段標(biāo)識(shí)符,盡管它們來(lái)自不同的起源。腳本之間保持一種一致的通信協(xié)議,由 JavaScript 計(jì)時(shí)器驅(qū)動(dòng),該計(jì)時(shí)器定期地激活例程以檢查片段標(biāo)識(shí)符中的更改。
由于腳本必須了解彼此的地址并且它們自身之間必須協(xié)作以取得對(duì)協(xié)議的一致遵守,因此要確保信任。由于任何服務(wù)器交互都在每個(gè)組件本地并且與腳本間通信分離,因此不會(huì)暴露 cookie。
雖然仍不完美(例如,它依賴(lài)于設(shè)計(jì)行為以外的異常,并且查詢(xún)更改不如用事件激活來(lái)響應(yīng)更改),但是這個(gè)解決方案比任何其他方案都更接近于提供瀏覽器本地的、安全的、頁(yè)面中的跨域通信。
請(qǐng)注意:James Burke 是 AOL Developer Network 的一名開(kāi)發(fā)人員,他開(kāi)創(chuàng)了片段標(biāo)識(shí)符技術(shù)并將其構(gòu)建到最新版本的 Dojo Toolkit JavaScript 庫(kù)中。
瀏覽器制造商和開(kāi)發(fā)團(tuán)體當(dāng)前正在討論幾種可能的修改瀏覽器環(huán)境元素的方法,使其以 Ajax mashup 為構(gòu)建目標(biāo)。Web Hypertext Application Technology Working Group (WHATWG) 在其用于 Cross Document Messaging 機(jī)制的 Web Applications 1.0 Working Draft 的 7.3 節(jié)中提出了一個(gè)建議。Opera 瀏覽器已經(jīng)實(shí)現(xiàn)了此特性。它指定了不同域中的 DOM 對(duì)象之間協(xié)作通信的方法,該方法允許消息的接收方根據(jù)消息的起源來(lái)選擇所要響應(yīng)的消息。
Ian Hickson 以前任職于 Opera,現(xiàn)在任職于 Google。他提出了對(duì)現(xiàn)有的 XMLHttpRequest
對(duì)象的跨站點(diǎn)擴(kuò)展。他的提議包括對(duì)發(fā)出請(qǐng)求的方式(包括報(bào)頭控制的限制和訪問(wèn)控制機(jī)制)的幾個(gè)修改。
Douglas Crockford 是任職于 Yahoo! 的一名 JavaScript 傳道者和架構(gòu)師,他是全球最有造詣的 JavaScript 語(yǔ)言專(zhuān)家之一。您可在他的個(gè)人 Web 站點(diǎn)上及通過(guò) Yahoo! Developer Network 找到很多他的解釋高級(jí) JavaScript 技術(shù)的展示和文章。Crockford 提出的另一項(xiàng)計(jì)劃是 JSON,它是一種 Ajax 應(yīng)用程序中廣泛使用的數(shù)據(jù)交換格式,其主要原因是易于被 JavaScript 解析并且不像 XML 那樣冗余。Crockford 編寫(xiě)了兩個(gè)提議來(lái)將 mashup 敏感的元素構(gòu)建到瀏覽器中。
幾個(gè)絕妙提議可幫助您應(yīng)對(duì)此困境:
JSONRequest
提議:瀏覽器實(shí)現(xiàn)一個(gè)新對(duì)象,其運(yùn)作方式類(lèi)似于現(xiàn)有的 XMLHttp
對(duì)象,作出了以下幾點(diǎn)修改: JSONRequest
將免除同源策略。 JSONRequest
將只接受有效的 JSON 文本,確保不將原始的可執(zhí)行代碼發(fā)送執(zhí)行。 <module>
標(biāo)記提議:新的 HTML 標(biāo)記將頁(yè)面分隔成彼此不受影響但可安全地通信的模塊集合: <module>
標(biāo)記將能夠訪問(wèn)第三方資源,免除同源策略。 請(qǐng)參閱 參考資料 中關(guān)于這些提議的詳細(xì)信息的鏈接。
![]() ![]() |
![]()
|
![]() |
|
作為開(kāi)發(fā)人員,我們都與這些討論的結(jié)果息息相關(guān)。通過(guò)參加討論,您可幫助設(shè)計(jì)最靈活、安全的瀏覽器改進(jìn),使所有人都能構(gòu)建健壯而安全的富 Web 應(yīng)用程序。我鼓勵(lì)您去尋找倡導(dǎo)瀏覽器改進(jìn)的瀏覽器供應(yīng)商和組織,并參與以下活動(dòng):
您可在本文的 參考資料 部分找到可作為起點(diǎn)的鏈接。
XMLHttpRequest
:閱讀 Ian Hickson 的更新后的提議。JSONRequest
和 <module>
標(biāo)記:閱讀 Douglas Crockford 的關(guān)于 mashup 安全問(wèn)題的解決方案的提議。XMLSocket
對(duì)象 和 cross-domain.xml 文件:了解 XMLSocket 對(duì)象和跨域策略文件如何實(shí)現(xiàn)運(yùn)行 Flash Player 的計(jì)算機(jī)與其他由 IP 地址或域名標(biāo)識(shí)的服務(wù)器之間的通信。聯(lián)系客服