mashup 是一個(gè) Web 應用程序,它集成了來(lái)自多個(gè)源的內容并將其交付到一個(gè)頁(yè)面中進(jìn)行顯示。服務(wù)器向每個(gè)內容源發(fā)出請求,解析收到的信息,并將結果綜合到一個(gè)頁(yè)面中發(fā)給瀏覽器,如 圖 1 所示。

Asynchronous JavaScript + XML(Ajax)應用程序 使 Web 頁(yè)面能從服務(wù)器獲取內容并使用 JavaScript™ 代碼異步地在適當位置進(jìn)行自我更新,如 圖 2 所示。這樣,用戶(hù)就可以與富用戶(hù)界面 (UI) 進(jìn)行交互而無(wú)需重新加載整個(gè)頁(yè)面。服務(wù)器向瀏覽器發(fā)送初始頁(yè)面,后者回調服務(wù)器以獲取更新后的內容。異步的 JavaScript 代碼調用頻繁使用 XML 來(lái)編碼數據;但是,其他的數據格式則更通用,如 JavaScript Object Notation (JSON)、HTML 和分隔文本。

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