JavaScript之跨域解決方式

蟹丸發表於2018-12-02
平時工作中經常被JavaScript跨域問題所困擾,其實有很多種解決方式,下面給大家介紹常用的幾種:

1.jsonp解決跨域問題

客戶端程式碼:

<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8">
<title>jsonp-跨域</title>
<script type="text/javascript" src="resources/js/jquery-1.8.3.min.js"></script>
<script type="text/javascript">
    function callbackFn(data){
        data = typeof data != 'string' ? JSON.stringify(data) : data;
        console.log('callback:'+data);
    }
    function jsonpFn(){
        $.ajax({
            type:"get",
            dataType:"jsonp",
            url:"http://localhost:9393/ccy_server/server.jsp",
            jsonpCallback:"callbackFn",
            success:function(data){
                data = typeof data != 'string' ? JSON.stringify(data) : data;
                console.log('success.data:'+data);
            }
        });
    }
    function ajaxFn(){
        var xmlhttp = window.XMLHttpRequest ? new XMLHttpRequest() : new ActiveXObject("Microsoft.XMLHTTP");
        var url = "http://localhost:9393/ccy_server/server.jsp";
        xmlhttp.onreadystatechange = function(){
            if(xmlhttp.readyState==4){
                if(xmlhttp.status==200){
                    callbackFn(xmlhttp.responseText);
                }
            }
        }
        xmlhttp.open('GET',url,true);
        xmlhttp.send(null);
    }
    ajaxFn();
    //jsonpFn();
</script>
</head>
<body>

</body>
</html>複製程式碼

服務端程式碼:

<%@ page language="java" contentType="text/html; charset=UTF-8"
    pageEncoding="UTF-8"%>
<%
    String result = "{\"name\":\"ccy\",\"age\":18,\"info\":{\"address\":\"wuhan\",\"interest\":\"playCards\"}}";
    out.println("callbackFn("+result+")");
%>複製程式碼

相信大家對此種方式並不陌生,需要引用jquery庫檔案,並且要與服務端進行協調處理。

我先寫了個簡單的ajax呼叫非同源的非同步請求直接報錯

JavaScript之跨域解決方式

執行jsonpFn方法

JavaScript之跨域解決方式

成功獲取服務端資訊!

2.window.name解決跨域問題

在客戶端瀏覽器中每個頁面都有一個獨立的視窗物件window,預設情況下window.name為空,在視窗的生命週期中,載入的所有頁面共享一個window.name並且每個頁面都有對此讀寫的許可權,window.name會一直存在當前視窗,但儲存的字串不超過2M。

http://localhost:8383/ccy_client/window_name.html程式碼

<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8">
<title>window.name-跨域</title>
<script type="text/javascript">
    window.name = "我是 window.name 字串";
    setTimeout(function(){
        window.location = "http://localhost:9393/ccy_server/window_name.html";
    },2000);
</script>
</head>
<body>

</body>
</html>複製程式碼

http://localhost:9393/ccy_server/window_name.html程式碼

<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8">
<title>window.name-跨域</title>
<script type="text/javascript">
    var str = window.name;
    console.log('ccy_server.window_name:'+str);
</script>
</head>
<body>

</body>
</html>複製程式碼

chrome列印資訊

JavaScript之跨域解決方式

上面是以window.location跳轉的方式獲取window.name字串資訊,平時開發中經常需要非同步獲取,請繼續往下看:

http://localhost:8383/ccy_client/window_name_iframe.html程式碼

<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8">
<title>window.name-跨域</title>
</head>
<body>
<script type="text/javascript">
    var boo = false;
    var iframe = document.createElement('iframe');
    var loadData = function() {
        if (boo) {
            var data = iframe.contentWindow.name;    //獲取window.name
            console.log(data); 
            //銷燬資料   
            iframe.contentWindow.document.write('');
            iframe.contentWindow.close();
            document.body.removeChild(iframe);
        } else {
            boo = true;
            iframe.contentWindow.location = "";    // 設定的代理檔案,iframe重新載入
        }  
    };
    iframe.src = 'http://localhost:9393/ccy_server/window_name_iframe.html';
    if (iframe.attachEvent) {
        iframe.attachEvent('onload', loadData);
    } else {
        iframe.onload  = loadData;
    }
    document.body.appendChild(iframe);
</script>

</body>
</html>複製程式碼

http://localhost:9393/ccy_server/window_name_iframe.html程式碼

<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8">
<title>window.name-跨域</title>
<script type="text/javascript">
    window.name = '我是 http://localhost:9393/ccy_server/window_name_iframe.html';
</script>
</head>
<body>

</body>
</html>複製程式碼

chrome列印資訊

JavaScript之跨域解決方式

成功獲取非同源地址的資料資訊,主要是通過iframesrc屬性,類似含有src屬性的標籤都可以成功處理跨域問題img,script

3.postMessage解決跨域問題

h5新特性,window.postMessage(msg,targetOrigin);

msg:傳入的字串資訊

targetOrigin:目標源(協議主機埠有效)

同樣藉助iframe進行跨域操作

http://localhost:8383/ccy_client/postMessage.html程式碼

<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8">
<title>postMessage-跨域</title>
</head>
<body>
<iframe id="ifr" src="http://localhost:9393/ccy_server/postMessage.html" style="display: none;"></iframe>
<br>
<input id="txt" type="text" style="width:600px;height:70px;"/>
<br>
<input id="btn" type="button" value="獲取9393資料" onclick="getData();" style="width:180px;height:60px;"/>
<script type="text/javascript">
    var data;
    function handleMsg(e){
        e = e || event;
        data = e.data;
        console.log('8383:'+e.data);
    }
    if(window.addEventListener){
        window.addEventListener('message', handleMsg);
    }else{
        window.attachEvent('onmessage', handleMsg);
    }
    function getData(){
        document.getElementById('txt').value=data;
        var msg = 'http://localhost:8383/ccy_client/postMessage.html';
        window.frames[0].postMessage(msg, 'http://localhost:9393');
    }
</script>

</body>
</html>複製程式碼

http://localhost:9393/ccy_server/postMessage.html程式碼

<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8">
<title>postMessage-跨域</title>
</head>
<body>
<script type="text/javascript">
    function handleMsg(e){
        e = e || event;
        console.log('9393:'+e.data);
    }
    if(window.addEventListener){
        window.addEventListener('message', handleMsg);
    }else{
        window.attachEvent('onmessage', handleMsg);
    }
    window.onload = function(){
        var msg = '我是 http://localhost:9393/ccy_server/postMessage.html';
        window.parent.postMessage(msg, 'http://localhost:8383');
    }
</script>

</body>
</html>複製程式碼

chrome列印資訊

JavaScript之跨域解決方式

成功獲取非同源資料,將非同源地址嵌入獲取資料頁面視窗。

4.Java解決跨域問題

通過客戶端頁面的ajax非同步請求同源頁面,再通過JavaHttpURLConnect或者HttpClient進行轉換即可,此處就不再贅述。

還有一種就是設定服務端的Header,公司產品gglyapi就是這麼處理的。

5.參考資料

www.sojson.com/blog/121.ht…

www.jianshu.com/p/43ff69d07…

《JavaScript權威指南》


相關文章