簡介
本文章主要探討前端發出跨域(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 GET和POST
|
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標籤來突破這個限制,透過這樣的方式我們也可以的寫出跨域登入系統或其他應用。
沒有留言:
張貼留言