1.同源策略javascript
指瀏覽器對不一樣源的腳本或者文本的訪問方式進行的限制。好比源a的js不能引入源b的元素屬性。html
所謂的同源是指兩個頁面具備相同的協議、主機(也是常說的域名)、端口,三個元素缺一不可。java
經過下列示例具體瞭解一下同源:node
同源策略限制了不一樣源之間的交互,(同源策略限制了不一樣源之間的交互主要針對js中的XMLHttpRequest等請求)下面這些狀況徹底不受同源策略的限制的。jquery
1.頁面中的連接,重定向以及表單提交是不會受同源策略的影響。(在你的域名www.foo.com下面提交一個表單到www.bar.com是徹底能夠的)nginx
2.跨域資源嵌入是容許的,若是瀏覽器限制了JavaScript,就不能讀寫加載的內容。(如前面提到的嵌入的<script src="..."></script>,<img>,<link>,<iframe>等
),固然,若是要阻止iframeweb
嵌入咱們的網站資源時(頁面或者js等),咱們能夠在web既然有這麼多的狀況是沒有同源策略限制的,那麼跨域問題是怎麼來的?ajax
2.跨域問題sql
前置條件是咱們在web服務器或者服務端腳本中設置ACCESS-CONTROL-ALLOW-ORIGIN頭部,若是設置了這些頭部而且容許某些域名跨域訪問,則瀏覽器就會跳過同源策略的限制返回對應的內容。此外,若是你不是經過瀏覽器
json
獲取資源,好比你經過一個Python腳本調用接口或者獲取js文件,也不在這個限制範圍以內。
1.AJAX跨域
經過AJAX調用其它域的接口會有跨域問題。好比:我在http://www.foo.com/index.html
中經過ajax調用請求http://www.bar.com/js/test.js
頁面,此時是會報錯的。
XMLHttpRequest cannot load http://www.bar.com/js/test.js.
No 'Access-Control-Allow-Origin' header is present on the requested resource.
Origin 'http://www.foo.com' is therefore not allowed access.
這是由於咱們的WEB服務器沒有設置ACCESS-CONTROL-ALLOW-ORIGIN
頭部,默認狀況下是禁止跨域引用資源的。固然這裏有一點要注意,其實這個跨域請求是發送成功了的,服務器也有返回test.js內容,只是瀏覽器禁止
Javascript去取response的數據而已。若是要設置ACCESS-CONTROL-ALLOW-ORIGIN頭部,nginx可使用下面的代碼
add_header 'Access-Control-Allow-Origin' 'http://www.foo.com';
add_header 'Access-Control-Allow-Credentials' 'true';
add_header 'Access-Control-Allow-Methods' 'GET,POST';
另外,咱們看到直接經過Javascript去取iframe中的元素也是會報錯的,由於域名不一樣。報錯以下所示
Uncaught SecurityError: Failed to read the 'contentDocument' property from 'HTMLIFrameElement': Blocked a frame with origin "http://www.foo.com" from accessing a frame with origin "http://foo.com".
The frame being accessed set "document.domain" to "foo.com", but the frame requesting access did not. Both must set "document.domain" to the same value to allow access.
這時由於咱們的主域名相同,所以能夠在index.html和test.html中設置document.domain='foo.com'
來訪問iframe中的元素。注意,是兩個域名下面的文件都要設置,即使是一樣的主域名。固然這是特例,若是是兩個徹底不一樣
的域名,是沒有辦法的,你不能把www.foo.com
的domain
設置成www.163.com
。
此外,在index.html裏面也能夠看到經過<script>,<iframe>
等標籤都是能夠跨域內嵌資源的。
# index.html
建立一個回調函數,而後在遠程服務上調用這個函數而且將JSON 數據形式做爲參數傳遞,完成回調。 將JSON數據填充進回調函數 <!DOCTYPE html> <html> <head> <title>test cross domain</title> <script src="/js/jquery.js"></script> <script src="http://www.bar.com/js/test.js"></script> <script> $(function(){ document.domain = 'foo.com'; //1 註釋掉則會報錯 var ifr = document.getElementById("testframe"); ifr.onload = function(){ var doc = ifr.contentDocument || ifr.contentWindow.document; alert(doc.getElementsByTagName("h1")[0].childNodes[0].nodeValue); } }); $.ajax("http://www.bar.com/js/test.js"); //2 報錯 </script> </head> <body> <h1>Test Cross Domain</h1> <iframe id="testframe" src="http://foo.com/test.html"></iframe> </body> </html>
固然還能夠經過iframe,location.hash,window.name,HTML5的postMessage
iframe,location.hash,window.name,HTML5的postMessage等方法來實現跨域資源訪問
2.JSONP跨域訪問(JSON+padding):
JSONP也是在開發中常見的內容,在jQuery中有封裝,經過ajax請求多帶上一個jsonp參數便可。JSONP也可以實現跨域訪問資源。可是它的實現原理跟ajax沒有多大關係,它是經過動態插入<script>
標籤來實現資源訪問的,在實際jsonp接口中,會讓你傳一個函數名過去,而後返回的數據中回調函數名就是你傳的函數名,回調函數的參數就是你封裝的jsonp格式,jQuery中的jsonp實現原理
基本上就是這樣實現的。
# jsonp.html
<script type="text/javascript"> function callback(data) { alert(data.message); } function addScriptTag(src){ var script = document.createElement('script'); script.src = src; document.body.appendChild(script); } window.onload = function(){ addScriptTag("http://www.foo.com/js/outer.js"); } </script> # outer.js callback({message:"success"});