跨域的主要方法

weixin_34162695發表於2018-01-18

一、JSONP

利用<script>不受瀏覽器同源策略的限制特性,來跨域進行引入資源,前提需要在自己專案中建立好介面,協商好對方後端返回這個介面的呼叫並且給這個介面傳入引數;
如下程式碼:

位於http://a.com:9000/A.html的程式碼:
HTML:
...
<div id="wrap">
        <h1>我是A站</h1>
        <button id="btn">點選變顏色</button>
</div>
...
JS:
btn.addEventListener("click",fn);
function fn() {
    var script = document.createElement("script"); //動態的建立一個script;
    script.src="http://b.com:8080/getcolor?type=setColor"; //設定請求的地址
    document.body.appendChild(script);
        }
function setColor(tinct){      //建立一個介面,當請求返回這個介面的呼叫;
     var h1 = document.querySelector("h1");   
     h1.style.color = tinct;
        }

效果圖如下:

8084817-3add832c4283c493.png

這裡有一個按鈕,點選之後標題的顏色可以改變。http://b.com:8080/getcolor?type=setColor是一個需要請求的地址,這個地址將會返回一個介面的呼叫並給這個介面傳入引數setColor(color),這時就需要後端來提供了。
後端程式碼如下:

位於http://b.com:8080/A.html的程式碼(這裡是nodejs的伺服器):
function random(a,b){
            return a+Math.round(Math.random()*(b-a))
        }
function getRandColor(){
            var arr = ["#"];
            for (var i = 0; i < 3; i++) {
                arr.push(random(0,255).toString(16));
            }
            return arr.join("");
}      //這兩個方法將會返回一個隨機的十六進位制顏色碼;
···
            var color = getRandColor();
            var type = pathObj.query.type; //讀取請求連線裡面的介面的函式名;
            res.end(type+"("+"'"+color+"'"+")");
           //返回一個函式的呼叫,這時將返回setColor('#******');

效果如下:


8084817-07839a812929025a.png

二、CORS

與JSONP相比,CORS支援所有型別的HTTP請求而jsonp只支援GET請求。JSONP的優勢在於支援老式瀏覽器,以及可以向不支援CORS的網站請求資料。
同樣的需求這次使用CORS來進行實現,這裡需要我們使用Aajx來請求。
前端程式碼如下:

var btn = document.querySelector("#btn");
        btn.addEventListener("click",ajax);
var lock = false;   
        function ajax(){
            if (lock) {
                return;
            }
            var xhr = new XMLHttpRequest();
            xhr.open("get","http://b.com:8080/getcolor",true); 
           //這裡請求的是B站的資源;
            xhr.send();
            lock = true;
            xhr.onload = function(){
                if ((xhr.status>=200&&xhr.status<300)||xhr.status===304) {
                    setColor(xhr.response);
                    lock = false;
                }
            }
        }
        function setColor(tinct){
            var h1 = document.querySelector("h1");
            h1.style.color = tinct;
        }

CORS的重點是後端程式碼如下:

var color = getRandColor();//這裡呼叫的函式,返回了一個十六進位制的顏色碼
res.setHeader("Access-Control-Allow-Origin", "*")
//設定響應頭資訊Access-Control-Allow-Origin為“*”
res.end(color);

後端把Access-Control-Allow-Origin設定為“*”,意味著這可以允許所有的來訪問的域名;
效果如下:


8084817-5281d8419d43b409.png

三、降域

一個網頁巢狀了一個iframe指向另一個源,可以顯示裡面的內容但是無法使用js去操作它,如果想要js去操作裡面的內容,並且是主域名和埠號相同的情況下,我們可以使用降域的方法去實現。
A站程式碼如下:

<h1>我是A站</h1>
<iframe src="http://b.me.com:9000/b.html" id="into" name="B"></iframe>
//iframe 指向http://b.me.com:9000/b.html
 <button>點選變顏色</button>
...
   document.querySelector('button').addEventListener('click', function(){
         var inner = window.frames["B"]
         inner.document.querySelector('h1').style.color = "red";
         inner.document.querySelector('p').innerText = "我被A站變成紅色的了";
})
       document.domain = "me.com";   將他們降域為me.com;

B站程式碼如下:

<h1>我是B站</h1>
    <p></p>
...
document.domain = "me.com";
...

效果如下:


8084817-a4c5ebee3b9c0cd9.png

A站域名為a.me.com、B站域名為b.me.com、利用document的domain屬性,將兩個域名同時設定為“me.com”,讓他們實現降域並且能跨域操作。
效果如下:


8084817-d6942f4c2a158a29.png

四、postMessage

這個是html5的新特性。相對於降域通過這個方法可以實現不同域名、埠下的跨域操作,同樣實現上面的操作,postMessage方法程式碼如下:

A站程式碼:
 document.querySelector('button').addEventListener('click', function(){
          inner.postMessage("red","http://b.com:8080/b.html")
})   //將向"http://b.com:8080/b.html"跨域傳送“red”;
B站程式碼:
window.addEventListener("message",function (e) {
            document.querySelector("h1").style.color = e.data;
        })

這裡A站域名為a.com:9000,B站域名為b.ocm:8080,他們的域名和埠和是不同的也同樣實現了跨域操作,利用postMessage()方法,這裡它有兩個引數,第一個引數是所要傳送的資訊,第二個引數是需要傳送的地址,在B站這裡,需要監聽"message"時間,它所事件物件有三個重要的屬性:data代表了所傳過來的資訊;origin發出請求的協議、域名和埠號如http://a.com:9000;source對傳送訊息的視窗物件的引用;
postMessage效果如下:

8084817-3f21508590132370.png

相關文章