同源策略、跨域、json和jsonp
同源策略
源(origin)就是協議、域名和端口號。若地址裏面的協議、域名和端口號均相同則屬於同源。
以下是相對於 http://www.a.com/test/index.html 的同源檢測
? http://www.a.com/dir/page.html ----成功
? http://www.child.a.com/test/index.html ----失敗,域名不同
? https://www.a.com/test/index.html ----失敗,協議不同
? http://www.a.com:8080/test/index.html ----失敗,端口號不同
同源策略是瀏覽器的一個安全功能,不同源的客戶端腳本在沒有明確授權的情況下,不能讀寫對方資源
跨域
1、什麽是跨域
受前面所講的瀏覽器同源策略的影響,不是同源的腳本不能操作其他源下面的對象。想要操作另一個源下的對象是就需要跨域。
2、跨域的實現方式
(1)降域 document.domain
同源策略認為域和子域屬於不同的域,如:child1.a.com 與 a.com,child1.a.com 與 child2.a.com,xxx.child1.a.com 與 child1.a.com
兩兩不同源,可以通過設置 document.damain=‘a.com‘,瀏覽器就會認為它們都是同一個源。想要實現以上任意兩個頁面之間的通信,兩個頁面必須都設置documen.damain=‘a.com‘。
此方式的特點:
1. 只能在父域名與子域名之間使用,且將 xxx.child1.a.com域名設置為a.com後,不能再設置成child1.a.com。
2. 存在安全性問題,當一個站點被攻擊後,另一個站點會引起安全漏洞。3. 這種方法只適用於 Cookie 和 iframe 窗口。
(2)JSONP跨域
采用jsonp跨域也存在問題:
1. 使用這種方法,只要是個網站都可以拿到b.com裏的數據,存在安全性問題。需要網站雙方商議基礎token的身份驗證。
2. 只能是GET,不能POST。
3. 可能被註入惡意代碼,篡改頁面內容,可以采用字符串過濾來規避此問題。
(3)CORS
CORS是一個W3C標準,全稱是"跨域資源共享"(Cross-origin resource sharing)。它允許瀏覽器向跨源服務器,發出XMLHttpRequest請求,從而克服了AJAX只能同源使用的限制。剛才的例子中,在b.com裏面添加響應頭聲明允許a.com的訪問,代碼:Access-Control-Allow-Origin: http://a.com然後a.com就可以用ajax獲取b.com裏的數據了。
(4)其它方法
1. HTML5的postMessage方法
2. window.name
3. location.hash
json和jsonp
- JSON是一種基於文本的數據交換方式(不支持跨域),或者叫做數據描述格式,是數組和對象的嵌套,而JSONP是一種非官方跨域數據交互協議。簡單地使用json並不能支持跨域資源請求,為了解決這個問題,需要采用jsonp數據交互協議。
- 同源下的前後端數據交換格式確定使用json了,如果想獲取別人網站上提供的數據怎麽做到呢?也就是跨域讀取數據問題,json是不行的,因為json只是普通的文本格式,能讓你這樣就輕松拿到那服務端就沒有任何安全和保密性可言了,所以瀏覽器使用了同源策略來限制文件獲取。最後的結果就是只有像img、script、iframe這類可以指定src屬性的標簽有跨域獲取別人網站上數據(圖片,腳本,源文件其實都是數據)的能力。比如:
<img src="http://img30.360buyimg.com/jgsq-productsoa/jfs/t2407/323/1635505465/47386/f2d89d88/56615e00N7a475ee6.jpg" /> <script src="http://apps.bdimg.com/libs/jquery/2.1.4/jquery.min.js"></script>
- 然而,眾所周知,js文件的調用不受跨域與否的限制,因此如果想通過純web端跨域訪問數據,只能在遠程服務器上設法將json數據封裝進js格式的文件中,供客戶端調用和進一步處理,這就是jsonp協議的原理。該協議的一個要點就是允許用戶傳遞一個callback參數給服務端,然後服務端返回數據時會將這個callback參數作為函數名來包裹住JSON數據,這樣客戶端就可以隨意定制自己的函數來自動處理返回數據了。
-
簡單的說,就是json不支持跨域,而js可以跨域,因此在服務器端用客戶端提供的js函數名將json數據封裝起來,再將函數提供給客戶端調用,從而獲得json數據。開發過程中,如果出現類似 “Origin ****** is not allowed by Access-Control-Allow-Origin.” 的錯誤,則可能是由於json數據不支持跨域導致的,應考慮使用jsonp協議。如果出現類似 ”SyntaxError: Unexpected token ‘:‘. Parse error.“ 的錯誤,則可能是由於返回的json數據沒有用”callback“傳遞的函數名封裝導致的。
例如:網站A需要獲取網站B的數據,網站B說我給你們一個方法:
1. 你們使用<script src="http://www.B.com/open.js"></script>標簽先獲取到open.js文件(網站B的責任),這裏邊有你們需要的數據。
2. 你們獲取數據後處理數據的方法名必須命名為foo(數據請求者的責任和義務)
這裏相當於B網站和請求獲取數據者之間建立了一個協議,要求請求者務必按照規則辦事,如果請求者不能同時遵守上面兩條就不能按預期獲取數據。
- jsonp全名叫做json with padding,很形象,就是把json對象用符合js語法的形式包裹起來以使其它網站可以請求得到,也就是將json數據封裝成js文件;
- json是理想的數據交換格式,但沒辦法跨域直接獲取,於是就將json包裹(padding)在一個合法的js語句中作為js文件傳過去。這就是json和jsonp的區別,json是想要的東西,jsonp是達到這個目的而普遍采用的一種方法,當然最終獲得和處理的還是json。所以說json是目的,jsonp只是手段。json總會用到,而jsonp只有在跨域獲取數據才會用到。
- 理解了json和jsonp的區別之後,其實ajax裏的跨域獲取數據就很好理解和實現了,同源時候並沒有什麽特別的,直接取就行,跨域時候需要拐個彎來達到目的。
- 附上jquery中ajax請求json數據實例:
//同源 $.ajax({ url:"persons.json", success:function(data){ console.log(data); //ToDo.. } }); //跨域 $.ajax({ url:"http://www.B.com/open.php?callback=?", dataType:"jsonp", success:function(data){ console.log(data); //ToDo.. } });
同源策略、跨域、json和jsonp