WEB跨域問題

跨域主要分爲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;
                    }

                })
相關文章
相關標籤/搜索
本站公眾號
   歡迎關注本站公眾號,獲取更多信息