學習 同源策略,jsonp,跨域 隨記
- 同源策略不阻止將動態指令碼元素插入文件中
2.注意:jquey是不支援post方式跨域的。
為什麼呢?
雖然採用post +動態生成iframe是可以達到post跨域的目的,但這樣做是一個比較極端的方式,不建議採用.
也可以說get方式的跨域是合法的,post方式從安全形度上,被認為是不合法的, 萬不得已還是不要劍走偏鋒..
client端跨域訪問的需求看來也引起w3c的注意了,看資料說html5 WebSocket標準支援跨域的資料交換,應該也是一個將來可選的跨域資料交換的解決方案
理解跨域首先必須要了解同源策略。同源策略是瀏覽器上為安全性考慮實施的非常重要的安全策略。
何謂同源:
URL由協議、域名、埠和路徑組成,如果兩個URL的協議、域名和埠相同,則表示他們同源
什麼是跨域?
概念:只要協議、域名、埠有任何一個不同,都被當作是不同的域
a.同源策略
JS只能與同一個域中的頁面進行通訊.如:執行在 http://domain:port/app1/page.html;上的指令碼不能和http://domain:port/app3/page.html;的瀏覽器視窗或iframe 進行互動.不能訪問它的cookie,接收它的HTTP響應等(但它可以向任何其他源傳送HTTP請求);AJAX 和 webservice 也受此策略管束.這種手段就叫同源策略;
兩個指令碼被認為是同源的條件是:
協議相同(比如都是http://) ;埠相同(通常都是80) ; 域名相同;
如果這三個條件中有任何一條不滿足,就不允許兩個指令碼進行互動.如:www.mydomain.com上的指令碼不能訪問video.mydomain.com上的頁面 ,因為兩者的域名不同,雖然後者是前者的子域.同樣,它也不能訪問www.mydomain.com:8080上的頁面 ,因為埠不同,也不能訪問about:blank 因為協議不同(後者不是http://)
跨域資源共享(CORS)
CROS(Cross-Origin Resource Sharing)跨域資源共享,定義了必須在訪問跨域資源時,瀏覽器與伺服器應該如何溝通。CROS背後的基本思想就是使用自定義的HTTP頭部讓瀏覽器與伺服器進行溝通,從而決定請求或響應是應該成功還是失敗。
什麼是jsonp?
維基百科的定義是:JSONP(JSON with Padding)是資料格式 JSON 的一種“使用模式”,可以讓網頁從別的網域要資 料。
JSONP也叫填充式JSON,是應用JSON的一種新方法,只不過是被包含在函式呼叫中的JSON,例如:
callback({"name","trigkit4"});
JSONP由兩部分組成:回撥函式和資料。回撥函式是當響應到來時應該在頁面中呼叫的函式,而資料就是傳入回撥函式中的JSON資料。
在js中,我們直接用XMLHttpRequest請求不同域上的資料時,是不可以的。但是,在頁面上引入不同域上的js指令碼檔案卻是可以的,jsonp正是利用這個特性來實現的。
例如:
<script type="text/javascript">
function dosomething(jsondata){
//處理獲得的json資料
}
</script>
<script src="http://example.com/data.php?callback=dosomething"></script>
js檔案載入成功後會執行我們在url引數中指定的函式,並且會把我們需要的json資料作為引數傳入。所以jsonp是需要伺服器端的頁面進行相應的配合的。
<?php
$callback = $_GET['callback'];//得到回撥函式名
$data = array('a','b','c');//要返回的資料
echo $callback.'('.json_encode($data).')';//輸出
?>
最終,輸出結果為:dosomething(['a','b','c']);
如果你的頁面使用jquery,那麼通過它封裝的方法就能很方便的來進行jsonp操作了。
<script type="text/javascript">
$.getJSON('http://example.com/data.php?callback=?,function(jsondata)'){
//處理獲得的json資料
});
</script>
jquery會自動生成一個全域性函式來替換callback=?中的問號,之後獲取到資料後又會自動銷燬,實際上就是起一個臨時代理函式的作用。$.getJSON方法會自動判斷是否跨域,不跨域的話,就呼叫普通的ajax方法;跨域的話,則會以非同步載入js檔案的形式來呼叫jsonp的回撥函
JSONP的優缺點
JSONP的優點是:它不像XMLHttpRequest物件實現的Ajax請求那樣受到同源策略的限制;它的相容性更好,在更加古老的瀏覽器中都可以執行,不需要XMLHttpRequest或ActiveX的支援;並且在請求完畢後可以通過呼叫callback的方式回傳結果。
JSONP的缺點則是:它只支援GET請求而不支援POST等其它型別的HTTP請求;它只支援跨域HTTP請求這種情況,不能解決不同域的兩個頁面之間如何進行JavaScript呼叫的問題。
Jsonp原理:
首先在客戶端註冊一個callback (如:'jsoncallback'), 然後把callback的名字(如:jsonp1236827957501)傳給伺服器。注意:服務端得到callback的數值後,要用jsonp1236827957501(......)把將要輸出的json內容包括起來,此時,伺服器生成 json 資料才能被客戶端正確接收。
然後以 javascript 語法的方式,生成一個function , function 名字就是傳遞上來的引數 'jsoncallback'的值 jsonp1236827957501 .
最後將 json 資料直接以入參的方式,放置到 function 中,這樣就生成了一段 js 語法的文件,返回給客戶端。
客戶端瀏覽器,解析script標籤,並執行返回的 javascript 文件,此時javascript文件資料,作為引數,
傳入到了客戶端預先定義好的 callback 函式(如上例中jquery $.ajax()方法封裝的的success: function (json))裡.(動態執行回撥函式)
可以說jsonp的方式原理上和<script src="http://跨域/...xx.js"></script>是一致的(qq空間就是大量採用這種方式來實現跨域資料交換的) .JSONP是一種指令碼注入(Script Injection)行為,所以也有一定的安全隱患.
jsonp的原理:
首先在客戶端註冊一個callback (如:'jsoncallback'), 然後把callback的名字(如:success_jsonpCallback)傳給伺服器端對應的處理函式。
伺服器先生成需要返回給客戶端的 json 資料。然後以 javascript 語法的方式,生成一個function , function 名字就是傳遞上來的引數(jsoncallback)的值(success_jsonpCallback) 。
最後將 json 資料直接以入參的方式,放置到 function 中,這樣就生成了一段 js 語法的文件,返回給客戶端。
客戶端瀏覽器,解析script標籤,並將伺服器端返回的資料,作為引數,
傳入到了客戶端預先定義好的 callback 函式(如上例中jquery $.ajax()方法封裝的的success: function (json))裡。
實際上跨域是通過動態增加script來載入資料,無法直接獲得資料,所以需要使用回撥函式。
執行原理:
傳送請求時需要傳一個callback的回撥函式名到伺服器端,伺服器端拿到這個回撥函式名,再將返回資料用引數的形式反回到客戶端,這樣客戶端就能夠調到。
所以傳送請求URL的地址後面一定要上jsoncallback=?這樣的引數,jquery會將?號自動替換成自動生成的回撥函式的名稱。
所以最終的實際請求為:http://api.taobao.com/apitools/ajax_props.do&jsoncallback=jsonp1322444422697
所以和ajax的方式想比較,也就是callback函式一個是自動生成的函式名,一個是手工指定的函式名
原理的示例程式碼:
//客戶端的JAVASCRIPT程式碼
var script=document.createElement("script");
script.src="http://www.pl4cj.com:8888/5/6/action.php?param=123&callback="+fnName;
document.getElementsByTagName("head")[0].appendChild(script)
//伺服器端的PHP程式碼,一定要有callback來進行回撥,在這裡加上括號,是讓它以語句塊的方式來進行解析
<?php
<SPAN style="COLOR: #ff00ff">echo $_GET["callback"]."(".json_encode($_GET).");";
</SPAN>?