同源策略和跨域-總結


目錄:
1.同源策略
2.跨域
3.幾種跨域技術 - JSONP, CORS
 

 
1.同源策略
什么叫同源?
URL由協議、域名、端口和路徑組成,如果兩個URL的協議、域名和端口相同,則表示他們同源。相反,只要協議,域名,端口有任何一個的不同,就被當作是跨域。
e.g. 對於http://store.company.com/dir/page.html進行同源檢測:
URL 結果 原因
http://store.company.com/dir2/other.html 成功 僅路徑不同
http://store.company.com/dir/inner/another.html 成功 僅路徑不同 
https://store.company.com/secure.html 失敗 協議不同
http://store.company.com:81/dir/etc.html 失敗 端口不同
http://news.company.com/dir/other.html 失敗 主機名不同
 
同源策略  Same-Origin-Policy(SOP)
瀏覽器采用同源策略,禁止頁面加載或執行與自身來源不同的域的任何腳本。換句話說瀏覽器禁止的是來自不同源的"document"或腳本,對當前"document"讀取或設置某些屬性。
情景:
比如一個惡意網站的頁面通過iframe嵌入了銀行的登錄頁面(二者不同源),如果沒有同源限制,惡意網頁上的javascript腳本就可以在用戶登錄銀行的時候獲取用戶名和密碼。
 
瀏覽器中有哪些不受同源限制呢?
<script>、<img>、<iframe>、<link>這些包含 src 屬性的標簽可以加載跨域資源。但瀏覽器限制了JavaScript的權限使其不能讀、寫加載的內容。
 

 
2.跨域
跨域是指從一個域的網頁去請求另一個域的資源。比如從http://www.baidu.com/ 頁面去請求 http://www.google.com 的資源。
 

 
3.跨域技術-JSONP
JSONP是什么?
上面提到過包含src屬性的<script>標簽可以加載跨域資源。 JSONP就是利用<script>標簽的跨域能力實現跨域數據的訪問。
 
JSONP實現的原理
在這之前,先來介紹下我是如何簡單的開啟服務的。
使用python的SimpleHTTPServer模塊(2.x)(3.x中時http.server)The SimpleHTTPServer module has been merged into http.server in Python 3.0.
------------------------------------------------------------------------------------------------
如果你已經用過python,請跳過這里。
 
>>安裝python(注意設置環境變量 Path -- D:\Program Files\Python2.7.1;)
(驗證python安裝配置完成:打開cmd, 輸入python 有識別)
(cmd 切換工作目錄)
>>在工作目錄中執行
$ python -m SimpleHTTPServer 8088 (2.x)
$ python -m http.server 8088 (3.x)
>>服務啟動后,不要關閉該窗口;否則相當於殺死了該服務進程
 
------------------------------------------------我是分割線---------------------------------------
index.html,在8088端口提供服務
 1 <!doctype html>
 2 <html lang="en" ng-app="simpleApp">
 3 <head>
 4     <meta charset="UTF-8">
 5     <script src="scripts/vendor/angular.min.js"></script>
 6     <script src="scripts/vendor/angular-resource.min.js"></script>
 7     <script src="scripts/controllers/controllers.js"></script>
 8     <script src="scripts/services/services.js"></script>
 9     <link href="styles/bootstrap.css" rel="stylesheet">
10 
11     <!-- [跨域]step1. 通過擁有src屬性的標簽進行跨域調用 <script><img><iframe> -->
12     <script type="text/javascript" src="http://localhost:8090/remote.js"></script>
13 
14     <!-- [跨域]step2. 本地函數被跨域的遠程js調用,並接收遠程js帶來的數據 -->
15     <script type="text/javascript">
16         var localHandler = function(data){ 17  alert('我是本地函數,可以被跨域的remote.js文件調用,遠程js帶來的數據是:' + data.result); 18  }; 19     </script>
20 
21     <!-- [跨域]step3. JSONP client端的核心:實現動態查詢 22  怎么樣讓遠程JS知道它應該調用的本地函數叫什么名字? 23  client傳參告訴server"我想要一段調用xx函數的JS代碼,請返回給我";即client在發送請求URL時,指定回調函數-->
24     <script type="text/javascript">
25         // 得到航班信息查詢結果后的回調函數
26         var flightHandler = function(data){ 27             <!-- [跨域]step4. 處理server返回的數據:幾種格式 -->
28             /* JSONArray 29  * flightHandler([ 30  * {"code": "CA1998", "price": 1780, "tickets": 5 }, 31  * {"code": "CA2001", "price": 2090, "tickets": 10 } 32  * ]);*/
33             for(var i=0; i<data.length; i++){ 34  alert('你查詢的航班結果是:票價 ' + data[i].price + ' 元,' + '余票 ' + data[i].tickets + ' 張。'); 35  } 36 
37             /* JSON 38  flightHandler({ "code": "CA1998", "price": 1780, "tickets": 5 }); 39              */
40 // alert('你查詢的航班結果是:票價 ' + data.price + ' 元,' + '余票 ' + data.tickets + ' 張。');
41  }; 42         // 提供jsonp服務的url地址(不管是什么類型的地址,最終生成的返回值都是一段javascript代碼)
43         var url = "http://localhost:8090/remote.js?code=CA1998&callback=flightHandler"; 44         // 創建script標簽,設置其屬性
45         var script = document.createElement('script'); 46  script.setAttribute('src', url); 47         // 把script標簽加入head,此時調用開始
48  document.getElementsByTagName('head')[0].appendChild(script); 49     </script>
50     
51     <title>simpleApp</title>
52 </head>
53 <body>
54     <div ng-view></div>
55 </body>
56 </html>
View Code

remote.js,在8090端口提供服務,來模擬不同域的遠程文件(端口不同)

 1 alert("遠程文件");  2 localHandler({"result":"我是遠程js帶來的數據"});  3 
 4 //JSON
 5 flightHandler({  6     "code": "CA1998",  7     "price": 1780,  8     "tickets": 5
 9 }); 10 
11 //JSONArray
12 flightHandler([{ 13     "code": "CA1998", 14     "price": 1780, 15     "tickets": 5
16 }, { 17     "code": "CA2001", 18     "price": 2090, 19     "tickets": 10
20 }]);
View Code
 
JSONP的缺點
JSONP只支持 GET 請求。
 
支持JSONP的不同技術
>>AngularJS
1 myUrl ="http://localhost:8090/api/test?callback=JSON_CALLBACK"; 2 $http.jsonp(myUrl).success( 3      function(data){ 4  alert(data); 5  } 6 );
1.angularJS中使用$http.jsonp函數
2.指定callback和回調函數名,函數名為JSON_CALLBACK時,會調用success回調函數,JSON_CALLBACK必須全為大寫。
3.也可以指定其它回調函數,但必須是定義在window下的全局函數。
4.url中必須加上callback
5.當callback為JSON_CALLBACK時,只會調用success,即使window中有JSON_CALLBACK函數,也不會調用該函數。
 
>>Ajax
 1 myUrl ="http://localhost:8090/api/test";  2 $.ajax({  3   type:"GET",  4  url:myUrl,  5   dataType:"jsonp",  6   jsonp:"callback",  7   jsonpCallback:"jsonpCallback",  8   success:function(data){  9  alert(data.msg); 10  } 11 }); 12 function jsonpCallback(data){ 13  alert(data); 14 }
JSONP 是通過動態添加<script>標簽來調用服務器的腳本(<script>含有src屬性,src屬性沒有跨域限制);而 Ajax 是通過 XHR(XmlHttpRequest) 對象。兩者並沒有直接關系,以上只是Ajax封裝JSONP的一種方式。
 

 
4.跨域技術-CORS (CrossOrigin Resources Sharing,跨源資源共享)
CORS是什么?
CORS,是 HTML5 的一項特性,它定義了一種瀏覽器和服務器交互的方式來確定是否允許跨域請求。
相對於 JSONP 這種解決方案來說,使用CORS,不需要要求服務器以指定格式返回數據(包裝成JS腳本的格式:callback_func({ data }););CORS,只需要在服務器端做一些通用設置。
 
一個簡單有效的解決方案:SpringMvc+AngularJS通過CORS實現跨域方案

參考網站:
enable cross-origin resource sharing 對各種服務器設置的詳細介紹,主流瀏覽器支持一覽。
 
 
 


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM