跨域主要分爲ajax跨域和iframe跨域:css
ajax跨域:在一個window中請求另外一個項目的數據,域名發生改變,即爲ajax跨域。要支持ajax跨域有幾種方式,如:jsonp,CORS等。這裏主要介紹CORS方式。html
iframe跨域:iframe自己是支持跨域的,即在一個域名下的window支持請求另外一個域名下的數據顯示到iframe,而不會產生跨域問題。但此跨域iframe中不容許訪問父window中的屬性和函數。即parent.var和top.var和parent.fn和top.fn會出現跨域異常,此時主要解決的是跨域數據傳輸問題。java
CORS跨域:jquery
CORS跨域的主要思想是自定義HTTP響應頭從而讓瀏覽器和跨域服務器通訊。默認狀況下跨域訪問時在ajax和http協議中都是不被支持的,爲啦支持跨域ajax跨域,請求和響應都必須設置跨域支持參數。ajax
請求參數:使用jquery時設置crossDomain:true,若是要攜帶cookie需增長參數xhrFields: {withCredentials: true}。則請求格式爲:json
1 $.ajax({ 2 crossDomain:true, 3 xhrFields: { 4 withCredentials: true 5 }, 6 url:url, 7 data : data, 8 success: function(data, statusText, xhr){ 9 10 } 11 });
響應參數:響應時瀏覽器接收響應的響應頭的響應域名與當前域名不一致,也是不被接受的,會報跨域異常,除非響應頭中包含該域名的訪問控制容許的參數跨域
HttpServletResponse response = (HttpServletResponse) res;
response.setHeader("Access-Control-Allow-Origin", "http://fsp1.uce.cn:8005"); 瀏覽器
若是要容許跨域攜帶cookie,設置響應頭Access-Control-Allow-Credentials屬性爲true
response.setHeader("Access-Control-Allow-Credentials", "true");服務器
爲了統一響應參數,不用在每一個controller中設置響應頭。通常經過Filter實現響應頭的統一處理cookie
1 import java.io.IOException; 2 3 import javax.servlet.Filter; 4 import javax.servlet.FilterChain; 5 import javax.servlet.FilterConfig; 6 import javax.servlet.ServletException; 7 import javax.servlet.ServletRequest; 8 import javax.servlet.ServletResponse; 9 import javax.servlet.http.HttpServletResponse; 10 11 public class AccessFilter implements Filter { 12 13 @Override 14 public void init(FilterConfig filterConfig) throws ServletException { 15 16 } 17 18 @Override 19 public void doFilter(ServletRequest req, ServletResponse res,FilterChain chain) throws IOException, ServletException { 20 21 HttpServletResponse response = (HttpServletResponse) res; 22 response.setHeader("Access-Control-Allow-Origin", "http://fsp1.uce.cn:8005"); 23 response.setHeader("Access-Control-Allow-Credentials", "true"); 24 /*response.setHeader("Access-Control-Allow-Methods", "POST, GET, OPTIONS, DELETE"); 25 response.setHeader("Access-Control-Max-Age", "3600"); 26 response.setHeader("Access-Control-Allow-Headers", "x-requested-with"); */ 27 chain.doFilter(req, res); 28 } 29 30 @Override 31 public void destroy() { 32 33 } 34 35 }
這樣ajax請求就實現啦可帶cookie的跨域交互。
iframe跨域:iframe原生支持跨域。跨域iframe主要難在和父窗口進行數據交互。
父窗口向跨域iframe傳輸數據:主要分爲postMessage和window.name,postMessage只能在窗口加載完成後才能使用,若是是固定的iframe標籤,可直接獲取iframe.postMessage,若是是動態添加的iframe必須監聽iframe的load事件,在該事件中postMessage。window.name固然也必須在window存在後才能設置,也要設置在iframe的load事件中,但window.name屬性有個特色是隻要window存在,doument從新roload的時候,window.name是不變的,所以,對於要在iframe加載過程當中使用的數據,咱們能夠先讓iframe的window load一次,這次load是一個空白頁面,當空白頁面load完成事件設置window.name屬性,在設置window.name屬性後再修改iframe的src讓此window從新加載目標跨域頁面,這時在該跨域頁面加載過程當中就個經過window.name獲取到父頁面傳輸的數據。
主要有兩種狀況:
1>傳輸的數據在此跨域iframe加載完成後內部觸發事件時使用,可經過postMessage傳輸,此方法較爲簡單
var state = 1;
document.getElementById('#iframeId').addEventListener("load", function() { if(state == 1) { state = 0; this.contentWindow.postMessage(data,crossDomain) } }, true);
2>傳輸的數據在此跨域iframe加載過程當中調用,此時不能在使用postMessage,該方法只能執行於窗口加載完成後,即load事件後,但在加載過程當中若是獲取參數,該參數還未傳遞過來,此時必須使用window.name傳遞,window的name屬性在窗口從新加載內容的時候是不會改變的,最大支持2M。既然要在窗口load時就要讀取參數,那麼該參數必需要在窗口load以前設置進去,因此要首先load一次窗口,這次load的url爲一空白中間頁面,目的只是讓window加載而且設置window.name屬性,在設置以後改變iframe的url爲咱們的目標跨域url,則iframe重新出發load事件,此時load的過程當中就能夠獲取上次load中間頁面設置的window.name屬性就獲取到了父窗口的值
跨域iframe向父窗口傳遞數據「
此時iframe已經加載完成,使用postMessage比較方便,父窗口監聽跨域iframe的messge,進行相應的處理,好比調用自身的函數
window.onload = function() {
if(window.top == window.self) {
//當前窗口爲最頂層窗口
return;
} else {
//摺疊消息面板
document.body.onclick = function(event) {
//若是直接調用父頁面成功,則直接調用,若是調用失敗則爲跨域,向父頁面傳遞消息
try {
if(window.top.vm.settings.type) {
window.top.vm.openSetting(event);
}
} catch(e) {
window.top.postMessage('click', '*');
}
}
//皮膚設置
var settings = localStorage.settings;
var themes = settings ? JSON.parse(settings) : {
themes: "default"
}
var css = document.createElement('style');
css.type = 'text/css';
css.id = "themes-setting";
if(themes.themes == 'default') {
css.innerHTML = ".iconfont{color:#ff9372;}";
} else if(themes.themes == 'blue') {
css.innerHTML = ".iconfont{color:#23b7e5;}";
} else {
css.innerHTML = ".iconfont{color:#464c5b;}";
}
document.head.appendChild(css);
}
}
/**
* 監聽跨域iframe傳遞的消息
*/
window.addEventListener('message', function(e) {
var operate = e.data;
switch(operate) {
case 'click':
debugger
if(vm.settings.type){
vm.openSetting();
}
break;
default:
break;
}
})