2012年5月30日

跨域請求 (cross domain ajax)


簡介

本文章主要探討前端發出跨域(cross domain)的請求(request)的解法,瀏覽器基於安全性的原因,禁止javascript發出跨域的Request,在深入探討之前必須先解釋何謂跨域(cross domain)。

跨域

domain指的是網站的所在地址代稱,每個網站伺服器都會有一個IP,但這組地址實在不好記,因此DNS伺服器會幫助我們將一個容易記得的名稱(domain name)對應到我們伺服器的IP。跨域(cross domain)指的就是請求在其他的domain地址,而不是本身伺服器位置。例如www.a.com發出request至www.b.com這就是跨域的行為。

解決方法

在前端如果要對不同domain發出請求解決方法大致上可以分為兩種,一為『動態script』、二為『代理伺服器』,動態script指的是透過javascript或jQuery的方式組出;而代理伺服器的方式則使透過一個代理人或中間人(server)代替我們對外部domain發出請求,client僅對自己的domain service發出請求,這個service會代替你處理後續並把結果回傳給你,本文章中並不會實作這個方式。


首先我們先介紹與實作第一種方式:《動態script》


觀察下面程式碼
<script> fuction sayHello(){ alert("hello"); } sayHello(); </script> 當我們進入網站就會看到hello的警示訊息,有人說這有甚麼難?
好嘛!!先別緊張好戲在後頭~


假設我們把sayHello()這段程式碼而外放在hello.js的檔案中,然後將其引入,如下
<script> fuction sayHello(){ alert("hello"); } </script> <script type="text/javascript" src="hello.js"> </script>

執行它,結果不變(我沒有再耍你),好戲上場了,如果這個hello.js在其他的網路位置上,那結果還會是一樣的嘛?
這是當然的,不然我們的jQuery是怎麼加入進來的,那跟我們的跨域請求有甚麼關係呢!?假如你使用下面程式碼引入jQuery函式庫,我們可以看到瀏覽器會將jQuery的程式碼載入到網站上。


上圖可以看到我們從code.jquery.com這個外部domain上送出GET請求,取得jquery.min.js程式碼
了解script的原理後,我們就可以利用這點進行跨域請求的實作了。

情境 : 這邊假設我們的網域為www.a.com,www.b.com提供一個通用的登入系統(像是FB的登入),當我們要使用domain b的登入系統時就必須發出跨domain的發出登入請求到www.b.com。


前端程式碼
<html> <head> <script type="text/javascript"> // data 為domainB帶回的結果 function loginDomainB(data){ console.log(data); } </script> <script type="text/javascript" src="http://localhost:8080/MemberAction.do?op=999"></script> </head> <body> </body> </html>

後端程式碼

實作方式可以使用任何的語言,主要就是在字串中呼叫前端對應的function,在裏頭塞入JSON資料。 private ActionForward crossLogin(ActionMapping mapping, MemberActionForm form, HttpServletRequest request, HttpServletResponse response, HttpSession session) { String result = "loginDomainB({membername:'augus',logintime:" + System.currentTimeMillis() + "})"; System.out.println(result); try { response.getOutputStream().write(BytesUtil.toBytes(result)); } catch (IOException e) { e.printStackTrace(); } return null; }
建置完畢,我們趕快先來測試server的連結

測試完畢,打開測試html實際觀察結果吧,結果如下

附註

 動態script與ajax功能比較

Ajax
動態script
跨瀏覽器兼容性
No
Yes
強制的跨域瀏覽器安全
Yes
No
是否能接收HTTP狀態碼
Yes
No (fails on any HTTP status other than 200)
是否支持HTTP GETPOST
Yes
No (GET only)
能否發送/接收HTTP
Yes
No
能否接收XML
Yes
Yes (but only embedded in a JavaScript statement)
能否接收JSON
Yes
Yes (but only embedded in a JavaScript statement)
是否提供同步和異步調用
Yes
No (asynchronous only)

結論

我們常常可以看到跨域的應用,例如google各種應用同步登入的機制或是Facebook提供的登入系統,雖然我們沒辦法使用ajax進行跨域的請求,但是我們可以透過script標籤來突破這個限制,透過這樣的方式我們也可以的寫出跨域登入系統或其他應用。


如果你希望使用jQuery實作
你可以參考我的這篇文章跨域請求- JSONP 使用jQuery實作


沒有留言:

ShareThis