伺服器端可控情形的Javascript跨域訪問解決方案

來源:互聯網
上載者:User
在最近的一個web項目中為了實現bookmark功能碰到了javascript跨域訪問的問題。起初,在google上搜的很多解決方案並不適用於我的情形,只在有一篇文章中提到的遠程載入javascript方法從理論上看到瞭解決的希望。但可惜作者只是一筆帶過,並未用例子詳細說明,所以不得不摸索了一陣才把這個問題搞定。在此,希望通過本文為同樣被這個問題困擾的朋友們提供一個解決方案作為參考。如有錯誤,歡迎指正!

Bookmark是目前許多 web2.0 網站 (http://del.icio.us/, www.diigo.com 等)都提供的熱門feature。它能將互連網上自己喜歡的網頁收藏到 Bookmark 伺服器上。本文要解決的問題就發生在使用者提交網頁URL(還包括Tag,Notes等)給Bookmark伺服器時。
 
關於 URL 的提交至少可以有三種方式:
 
1.       登陸Bookmark伺服器的提交頁面,將要收藏的 URL 通過該頁面提交給伺服器。
2.       安裝瀏覽器外掛程式,通過外掛程式將 URL 提交給伺服器。
3.       從Bookmark伺服器動態載入 javascript 小工具到當前頁面,通過它來完成提交工作。(參考diigo的例子,收藏一個網頁連結到瀏覽器收藏夾,連結的URL是一段javascript代碼,它會從伺服器載入一段 javascript注入當前網頁)
 
第一種方式開發起來最簡單,但對使用者來講比較麻煩,每次都需要先登陸 Bookmark伺服器才能完成提交;第二種方式我並不熟悉外掛程式開發,而且使用者也不喜歡太多的外掛程式堆滿自己的瀏覽器;第三種方式開發難度小,又避免了每次登陸伺服器的麻煩,所以我最終採用了它。
 
上面講的第三種方式中動態載入的javascript小工具除了需要產生 UI 供使用者填寫資訊(URL, tag, notes等),當使用者點擊提交的時候,還要完成與伺服器通訊的功能。在沒有跨域訪問經驗的情況下,最先想到的當然是ajax!但很快就會發現根本行不通。
 
跨域訪問,簡單來說就是A網站的javascript代碼試圖訪問B網站,包括提交內容和擷取內容。由於安全原因,跨域訪問是被各大瀏覽器所預設禁止的。寫過跨域訪問ajax的朋友相信都遇到過被告知“沒有許可權”的情況。通過XMLHttp來發送資料給Bookmark伺服器的嘗試失敗了。於是,看到網上的一些資料,我又開始嘗試用javascript小工具在使用者網頁動態建立一個隱藏的 iframe,iframe的src指向伺服器的一個servlet,試圖通過調用iframe中提供的javascript來完成與伺服器的通訊。但不幸的是,使用者網頁中的 javascript代碼訪問iframe也被瀏覽器歸為跨域訪問(特指iframe的src 指向其它網站的情形),嘗試再次失敗。
 
最終,在一篇文章中看到,與iframe不同,如果A網站從B網站載入 javascript,A網站可以自由的訪問該javascript的內容,並不會被瀏覽器認為是跨域訪問。模仿剛才iframe的思路,當使用者點擊提交時,可以動態建立一個javascript對象,該對象的src指向Bookmark伺服器的一個 servlet,注意:URL、Tag、Notes、User、Password等資訊被作為src URL參數傳給伺服器。請看下面的代碼:
 
var url = "http://localhost:8080/Deeryard/BookmarkServlet?" +
           "url=" + url_source + "&" + "title=" + title + "&" +
"tag=" + tag + "&" + "notes=" + notes + "&" + "user=" + user + "&" + "password=" + password;
 
url = encodeURI(url);
   
//Submit to server with a trick
var js_obj = document.createElement( "script" );
js_obj.type = "text/javascript" ;
js_obj.setAttribute( "src" , url);
   
//Get response from server by appending it to document
document.body.appendChild(js_obj);
 
上面例子中,js_obj.setArrribute()將資訊作為src的URL參數提交給了Bookmark servlet。那麼使用者又如何取得伺服器的響應資訊呢?答案就是最末一行代碼,servlet的輸出必須是javascript代碼,它可以調用使用者網頁上的其他 javascript 函數,以及操作 dom 對象。下面的 servlet 代碼產生了一個 javascript 函數調用:
 
out.write("onServerResponse(INADEQUATE_INFORMATION);");
 
document.body.appendChild(js_obj) 執行後 onServerResponse( INADEQUATE_INFORMATION) 就會得到執行,使客戶網頁響應伺服器結果。這樣一個完整的通訊過程就完成了。
 
來總結一下這個案例,首先與很多跨域訪問的情形不同,本文提到的跨域訪問需要對伺服器端進行控制,即讓伺服器端 Servlet 來適應用戶端網頁 javascript 的需求;而其他一些常見的例子則對伺服器端沒有控制能力,比如從其他網站抓內容的小偷程式。另外,需要注意的是這種方法中實際用到了 get 方法來提交資訊,從一些資料上看到, get 方法每次提交的資訊不能超過 2k 。

聯繫我們

該頁面正文內容均來源於網絡整理,並不代表阿里雲官方的觀點,該頁面所提到的產品和服務也與阿里云無關,如果該頁面內容對您造成了困擾,歡迎寫郵件給我們,收到郵件我們將在5個工作日內處理。

如果您發現本社區中有涉嫌抄襲的內容,歡迎發送郵件至: info-contact@alibabacloud.com 進行舉報並提供相關證據,工作人員會在 5 個工作天內聯絡您,一經查實,本站將立刻刪除涉嫌侵權內容。

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.