前后端通信的那些事兒

一、同源策略

同源就是當(dāng)協(xié)議、域名和端口都一致時(shí),才算是同源,有一個(gè)不同都不是同源。

同源策略官方解釋就是,限制從一個(gè)源加載的文檔或腳本如何與來(lái)自另一個(gè)源的資源進(jìn)行交互。這是一個(gè)用戶(hù)隔離潛在惡意文件的關(guān)鍵的安全機(jī)制。

不是同源,主要會(huì)有以下限制:

  • cookie、LocalStorage和IndexDB無(wú)法讀取
  • DOM無(wú)法獲取
  • Ajax請(qǐng)求不能發(fā)送

二、前后端如何通信

  • Ajax ,受同源策略限制
  • WebSocket,不受同源策略限制
  • CORS,既支持跨域通信,也支持同源通信

三、如何創(chuàng)建Ajax

創(chuàng)建一個(gè)Ajax,主要考慮如下問(wèn)題:

  • XMLHttpRequest 對(duì)象的工作流程
  • 兼容性的處理
  • 事件的觸發(fā)條件
  • 事件的觸發(fā)順序
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8">
<script>
function loadXMLDoc()
{
  var xmlhttp;
  var txt,x,i;
// 判斷XMLHttpRequest是否存在
  if (window.XMLHttpRequest)
  {
    // IE7+, Firefox, Chrome, Opera, Safari 瀏覽器執(zhí)行代碼
    xmlhttp=new XMLHttpRequest();
  }
  else
  {
    // IE6, IE5 瀏覽器執(zhí)行代碼
    xmlhttp=new ActiveXObject("Microsoft.XMLHTTP");
  }
  xmlhttp.onreadystatechange=function()
  {
    if (xmlhttp.readyState==4 && xmlhttp.status==200)
    {
      xmlDoc=xmlhttp.responseXML;
      txt="";
      x=xmlDoc.getElementsByTagName("ARTIST");
      for (i=0;i<x.length;i++)
      {
        txt=txt + x[i].childNodes[0].nodeValue + "<br>";
      }
      document.getElementById("myDiv").innerHTML=txt;
    }
  }
  xmlhttp.open("GET","cd_catalog.xml",true);
  xmlhttp.send();
}
</script>
</head>
<body>

<h2>我收藏的 CD :</h2>
<div id="myDiv"></div>
<button type="button" onclick="loadXMLDoc()">獲取我的 CD</button>
 
</body>
</html>

創(chuàng)建一個(gè)Ajax的基本步驟:

  • (1)創(chuàng)建XMLHttpRequest對(duì)象,也就是創(chuàng)建一個(gè)異步調(diào)用對(duì)象。
  • (2)創(chuàng)建一個(gè)新的HTTP請(qǐng)求,并指定請(qǐng)求的方法、URL、是否異步處理請(qǐng)求及驗(yàn)證信息。
  • (3)為onreadystatechange 事件綁定方法,監(jiān)聽(tīng)狀態(tài)的改變。
  • (4)發(fā)送HTTP請(qǐng)求。

四、跨域通信的幾種方式

  • JSONP
    只支持GET請(qǐng)求
    利用script標(biāo)簽支持跨域的屬性,用script標(biāo)簽?zāi)玫桨藬?shù)據(jù)的方法(相當(dāng)于是返回了一段js代碼),在請(qǐng)求中包含callback,服務(wù)端注入?yún)?shù)后返回這個(gè)回調(diào)函數(shù),然后script標(biāo)簽?zāi)玫椒祷氐膉s代碼跨域直接運(yùn)行回調(diào),需要前后端的配合。
  • Hash
    原理是利用location.hash來(lái)進(jìn)行傳值。在url: http://a.com#helloword中的‘#helloworld’就是location.hash,改變hash并不會(huì)導(dǎo)致頁(yè)面刷新,所以可以利用hash值來(lái)進(jìn)行數(shù)據(jù)傳遞,當(dāng)然傳遞數(shù)據(jù)的大小是有限的。
  • postMessage
// 窗口A(yíng)(http://A.com)向跨域窗口B(http://B.com)發(fā)送信息
window.postMessage('data', 'http://B.com');

// 在窗口B中監(jiān)聽(tīng)
window.addEventListener('message', function(event){
     console.log(event.origin); // http://A.com
     console.log(event.source); // A的window
     console.log(event.data); // data
})
  • WebSocket
    特點(diǎn)包括:

(1)建立在 TCP 協(xié)議之上,服務(wù)器端的實(shí)現(xiàn)比較容易。
(2)與 HTTP 協(xié)議有著良好的兼容性。默認(rèn)端口也是80和443,并且握手階段采用 HTTP 協(xié)議,因此握手時(shí)不容易屏蔽,能通過(guò)各種 HTTP 代理服務(wù)器。
(3)數(shù)據(jù)格式比較輕量,性能開(kāi)銷(xiāo)小,通信高效。
(4)可以發(fā)送文本,也可以發(fā)送二進(jìn)制數(shù)據(jù)。
(5)沒(méi)有同源限制,客戶(hù)端可以與任意服務(wù)器通信。
(6)協(xié)議標(biāo)識(shí)符是ws(如果加密,則為wss),服務(wù)器網(wǎng)址就是 URL。

var ws = new Websocket('wss://echo.websocket.org');

ws.onopen = function(evt) {
    console.log('Connection open...');
    ws.send('Hello world!');
};

ws.onmessage = function (evt) {
    console.log('Received Message' + evt.data);
    ws.close();
};

ws.onclose = function (evt) {
    console.log('Connection closed');
}

  • CORS
    為什么CORS能支持跨域通信?
    瀏覽器會(huì)攔截Ajax請(qǐng)求,如果瀏覽器發(fā)現(xiàn)這個(gè)Ajax請(qǐng)求時(shí)跨域的,它會(huì)在HTTP請(qǐng)求頭中加一個(gè)origin。
最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
【社區(qū)內(nèi)容提示】社區(qū)部分內(nèi)容疑似由AI輔助生成,瀏覽時(shí)請(qǐng)結(jié)合常識(shí)與多方信息審慎甄別。
平臺(tái)聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀(guān)點(diǎn),簡(jiǎn)書(shū)系信息發(fā)布平臺(tái),僅提供信息存儲(chǔ)服務(wù)。

相關(guān)閱讀更多精彩內(nèi)容

友情鏈接更多精彩內(nèi)容