跨域就是:JavaScript出於安全方面的考慮,不容許跨域調用其餘頁面的對象。css
但在安全限制的同時也給注入iframe或是ajax應用上帶來了很多麻煩。html
簡單地理解就是由於JavaScript同源策略的限制,a.com 域名下的js沒法操做b.com或是c.a.com域名下的對象。前端
跨域的表現主要有:協議不一樣,主機名不一樣,端口號不一樣node
詳細的說明能夠看下錶:ajax
URL | 說明 | 是否容許通訊 |
---|---|---|
http://www.a.com/a.js http://www.a.com/b.js |
同一域名下 | 容許 |
http://www.a.com/lab/a.js http://www.a.com/script/b.js |
同一域名下不一樣文件夾 | 容許 |
http://www.a.com:8000/a.js http://www.a.com/b.js |
同一域名,不一樣端口 | 不容許 |
http://www.a.com/a.js https://www.a.com/b.js |
同一域名,不一樣協議 | 不容許 |
http://www.a.com/a.js http://70.32.92.74/b.js |
域名和域名對應ip | 不容許 |
http://www.a.com/a.js http://script.a.com/b.js |
主域相同,子域不一樣 | 不容許 |
http://www.a.com/a.js http://a.com/b.js |
同一域名,不一樣二級域名(同上) | 不容許(cookie這種狀況下也不容許訪問) |
http://www.cnblogs.com/a.js http://www.a.com/b.js |
不一樣域名 | 不容許 |
特別注意兩點:json
第一,若是是協議和端口形成的跨域問題「前臺」是無能爲力的,跨域
第二:在跨域問題上,域僅僅是經過「URL的首部」來識別而不會去嘗試判斷相同的ip地址對應着兩個域或兩個域是否在同一個ip上。
「URL的首部」指window.location.protocol +window.location.host,也能夠理解爲「Domains, protocols and ports must match」。安全
JSONP包含兩部分:回調函數和數據。服務器
回調函數是當響應到來時要放在當前頁面被調用的函數。cookie
數據就是傳入回調函數中的json數據,也就是回調函數的參數了。
function handleResponse(response){ console.log('The responsed data is: '+response.data); } var script = document.createElement('script'); script.src = 'http://www.baidu.com/json/?callback=handleResponse'; document.body.insertBefore(script, document.body.firstChild); /*handleResonse({"data": "zhe"})*/ //原理以下: //當咱們經過script標籤請求時 //後臺就會根據相應的參數(json,handleResponse) //來生成相應的json數據(handleResponse({"data": "zhe"})) //最後這個返回的json數據(代碼)就會被放在當前js文件中被執行 //至此跨域通訊完成
對於主域相同而子域不一樣的例子,能夠經過設置document.domain的辦法來解決。具體的作法是能夠在http://www.a.com/a.html和http://script.a.com/b.html兩個文件中分別加上document.domain = ‘a.com’;而後經過a.html文件中建立一個iframe,去控制iframe的contentDocument,這樣兩個js文件之間就能夠「交互」了。固然這種辦法只能解決主域相同而二級域名不一樣的狀況,若是你異想天開的把script.a.com的domian設爲alibaba.com那顯然是會報錯地!代碼以下:
www.a.com上的a.html
document.domain = 'a.com'; var ifr = document.createElement('iframe'); ifr.src = 'http://script.a.com/b.html'; ifr.style.display = 'none'; document.body.appendChild(ifr); ifr.onload = function(){ var doc = ifr.contentDocument || ifr.contentWindow.document; // 在這裏操縱b.html alert(doc.getElementsByTagName("h1")[0].childNodes[0].nodeValue); };
script.a.com上的b.html
document.domain = 'a.com';
這種方式適用於{www.kuqin.com, kuqin.com, script.kuqin.com, css.kuqin.com}中的任何頁面相互通訊。
備註:某一頁面的domain默認等於window.location.hostname。主域名是不帶www的域名,例如a.com,主域名前面帶前綴的一般都爲二級域名或多級域名,例如www.a.com實際上是二級域名。 domain只能設置爲主域名,不能夠在b.a.com中將domain設置爲c.a.com。
iframe、img、style、script等元素的src屬性能夠直接向不一樣域請求資源,jsonp正是利用script標籤跨域請求資源的簡單實現,因此這個和jsonp本質同樣,一樣須要服務端請求返回callback...形式。
var url="http://xxx.xxx.xxx?p1=1"; var script = document.createElement('script'); script.setAttribute('src', url); document.getElementsByTagName('head')[0].appendChild(script);
flash在跨域時惟一的限制策略就是crossdomain.xml文件,該文件限制了flash是否能夠跨域讀寫數據以及容許從什麼地方跨域讀寫數據。
位於www.a.com域中的SWF文件要訪問www.b.com的文件時,SWF首先會檢查www.b.com服務器目錄下是否有crossdomain.xml文件,若是沒有,則訪問不成功;若crossdomain.xml文件存在,且裏邊設置了容許www.a.com域訪問,那麼通訊正常。因此要使Flash能夠跨域傳輸數據,其關鍵就是crossdomain.xml。
自flash 10之後,若有跨域訪問需求,必須在目標域的根目錄下放置crossdomain.xml文件,且該根目錄下的配置文件稱爲「主策略文件」。若不存在主策略文件,則該域將禁止任何第三方域的flash跨域請求。
主策略文件對全站的跨域訪問起控制做用。
也能夠單獨在某路徑下放置僅對該路徑及其子路徑生效的crossdomain.xml配置文件,這須要在flash的AS腳本中使用以下語句來加載該配置文件:[具體的加載權限限制,將受後文中site-control策略的影響]
Security.loadPolicyFile("http://www.xxx.com/subdir/crossdomain.xml") |
crossdomain.xml需嚴格遵照XML語法,有且僅有一個根節點cross-domain-policy,且不包含任何屬性。在此根節點下只能包含以下的子節點:site-control、allow-access-from、allow-access-from-identity、allow-http-request-headers-from。下面將分別介紹這四個子節點:
每一個site-control標籤有且僅有屬性permitted-cross-domain-policies,該屬性指定相對於非主策略文件的其餘策略文件的加載策略。permitted-cross-domain-policies屬性值有以下狀況:
none: 不容許使用loadPolicyFile方法加載任何策略文件,包括此主策略文件。
master-only: 只容許使用主策略文件[默認值]。
by-content-type:只容許使用loadPolicyFile方法加載HTTP/HTTPS協議下Content-Type 爲text/x-cross-domain-policy的文件做爲跨域策略文件。
by-ftp-filename:只容許使用loadPolicyFile方法加載FTP協議下文件名爲 crossdomain.xml的文件做爲跨域策略文件。
all: 可以使用loadPolicyFile方法加載目標域上的任何文件做爲跨域策略文件,甚至是一 個JPG也可被加載爲策略文件![使用此選項那就等着被xx吧!]
如須要對網站某子目錄作單獨的flash跨域限制策略,在主策略文件中必須進行相應的site-control設置。
下面的例子將site-control策略配置爲可加載本服務器中其它的text/x-cross-domain-policy文件做爲跨域策略文件。
<cross-domain-policy> <site-control permitted-cross-domain-policies="by-content-type" /> </cross-domain-policy> |
allow-access-from標籤有三個屬性:
·domain:該屬性指定一個確切的 IP 地址、一個確切的域或一個通配符域(任何域)。只有domain中指定的域,纔有權限經過flash讀取本域中的內容。
可採用下列兩種方式之一來表示通配符域:
1.單個星號(*),如:<allow-access-fromdomain="*" />,表示匹配全部域和全部IP 地 址,此時任何域都可跨域訪問本域上的內容。[這是極不安全的!]
2.後接後綴的星號,表示只匹配那些以指定後綴結尾的域,如*.qq.com可匹配 game.qq.com、qq.com。形如www.q*.com或www.qq.*的爲無效配置。
Tips:當domain被指定爲IP地址時,只接受使用該IP做爲網址來訪問的來源請求[此時ip地址也就至關於一個域名而已],如domain被設置爲192.168.1.100時,使用http://192.168.1.100/flash.swf 來請求該域內容是容許的,可是使用指向192.168.1.100的域名www.a.com來訪問時[http://www.a.com/flash.swf]將會被拒絕,由於flash不懂得dns解析:)
·to-ports:該屬性值代表容許訪問讀取本域內容的socket鏈接端口範圍。可以使用to-ports="1100,1120-1125"這樣的形式來限定端口範圍,也可以使用通配符(*)表示容許全部端口。
·secure:該屬性值指明信息是否經加密傳輸。當crossdomain.xml文件使用https加載時,secure默認設爲true。此時將不容許flash傳輸非https加密內容。若手工設置爲false則容許flash傳輸非https加密內容。
下面的例子配置爲容許全部qq.com下的全部二級域名[包括qq.com自己]經過https訪問本域中的內容。
<cross-domain-policy> <allow-access-from domain="*.qq.com" secure="true" /> </cross-domain-policy> |
<allow-access-from-identity> <signatory> <certificate fingerprint="01:23:45:67:89:ab:cd:ef:01:23:45:67:89:ab:cd:ef:01:23:45:67" fingerprint-algorithm="sha-1"/> </signatory> </allow-access-from-identity> |
allow-access-from節點受權第三域提取本域中的數據,而 allow-http-request-headers-from 節點受權第三方域將數據以http頭的形式發送到本域中。[簡而言之,allow-access-from是控制讀取權限,allow-http-request-headers-from是控制以http頭形式的寫入權限]
allow-http-request-headers-from包含三個屬性:
·domain:做用及參數格式與allow-access-from節點中的domain相似。
·headers:以逗號隔開的列表,代表容許發送的http頭。可用通配符(*)表示所有 http頭。
·secure:做用及用法與allow-access-from節點中的secure相同。
在下面的示例中,任何域均可以向當前域發送 SOAPAction 標頭:
<cross-domain-policy> <allow-http-request-headers-from domain="*" headers="SOAPAction" /> </cross-domain-policy> |
不正確的crossdomain.xml策略將致使嚴重的安全問題,如信息泄露、CSRF等。從上文中能夠看出,在進行安全評估時,咱們應重點關注如下幾點:
1.allow-access-from標籤的domain屬性檢測:domain屬性應根據最小化原則按需設置,僅容許可信任的來源跨域請求本域內容。禁止將該屬性值設置爲「*」。
2.allow-http-request-headers-from標籤的domain屬性檢測:domain屬性應根據最小化原則按需設置,僅容許可信任的來源向本域跨域發送內容。禁止將該屬性值設置爲「*」。
3. site-control標籤的permitted-cross-domain-policies屬性檢測:根據業務的實際需求及可行性,對該屬性作相應設置。禁止將該屬性值設置爲「all」。