如何實(shí)現(xiàn)跨域

什么是同源策略

  • 同源策略限制從一個(gè)源加載的文檔或腳本如何與來(lái)自另一個(gè)源的資源進(jìn)行交互。這是一個(gè)用于隔離潛在惡意文件的關(guān)鍵的安全機(jī)制。
  • 一個(gè)源的定義:如果協(xié)議,端口(如果指定了一個(gè))和域名對(duì)于兩個(gè)頁(yè)面是相同的,則兩個(gè)頁(yè)面具有相同的源。

什么是跨域?跨域有幾種實(shí)現(xiàn)形式

  • 不同源的資源之間的交互就是跨域。
  • 實(shí)現(xiàn)跨域的幾種方式:

1.一些HTML標(biāo)簽和CSS語(yǔ)法能夠?qū)崿F(xiàn)跨源訪問(wèn):

  • <script src="..."></script>標(biāo)簽嵌入跨域腳本。
  • <link rel="stylesheet" href="...">標(biāo)簽嵌入CSS。由于CSS的松散的語(yǔ)法規(guī)則,CSS的跨域需要一個(gè)設(shè)置正確的Content-Type消息頭。
  • <img>嵌入圖片。
  • <video> 和 <audio>嵌入多媒體資源。
  • <object>, <embed> 和 <applet>的插件。
  • @font-face引入的字體。一些瀏覽器允許跨域字體,一些需要同源字體。
  • <frame> 和 <iframe>載入的任何資源。站點(diǎn)可以使用X-Frame-Options消息頭來(lái)阻止這種形式的跨域交互。

2.使用JSONP:

  • JSONP的原理就是通過(guò)script標(biāo)簽?zāi)軌蚩缬蚯度肽_本來(lái)實(shí)現(xiàn)跨域通信的。示例:

    btn.onclick = function () {
      var js = document.createElement('script')
      js.src = 'http://localhost:8080/jsonp?callback=renderPage'
      document.body.appendChild(js)
      document.body.removeChild(js)
    }
    
    function renderPage(data) {
      var node = ''
      for (var key in data) {
        node += '<li>' + data[key] + '</li>'
      }
      ct.innerHTML = node
    }
    

完整示例

3.使用cors:

  • 跨域資源共享( CORS )機(jī)制允許 Web 應(yīng)用服務(wù)器進(jìn)行跨域訪問(wèn)控制,從而使跨域數(shù)據(jù)傳輸?shù)靡园踩M(jìn)行。瀏覽器支持在 API 容器中(例如 XMLHttpRequest 或 Fetch )使用 CORS,以降低跨域 HTTP 請(qǐng)求所帶來(lái)的風(fēng)險(xiǎn)。

  • CORS與普通的Ajax通信的區(qū)別就在于使用CORS需要在目標(biāo)服務(wù)器的HTTP頭中設(shè)置一個(gè)字段,從而聲明哪些源站有權(quán)限訪問(wèn)哪些資源。如:

    服務(wù)器端:
    cors: function (res) {
      var data = router.news()
      res.setHeader("Access-Control-Allow-Origin", "*")
      res.end(JSON.stringify(data))
    }
    服務(wù)端返回的 Access-Control-Allow-Origin: * 表明,該資源可以被任意外域訪問(wèn)。
    如果服務(wù)端僅允許來(lái)自 http://foo.example 的訪問(wèn),該首部字段的內(nèi)
    容如下:Access-Control-Allow-Origin: http://foo.example
    

完整示例

4.降域:

  • 當(dāng)需要進(jìn)行跨域的資源位于統(tǒng)一頂級(jí)域下時(shí),可以更改它們的源來(lái)實(shí)現(xiàn)跨域訪問(wèn)。

  • 源的更改:頁(yè)面可能會(huì)更改其自己的來(lái)源,但有一些限制。腳本可以將 document.domain 的值設(shè)置為其當(dāng)前域或其當(dāng)前域的超級(jí)域。如果將其設(shè)置為其當(dāng)前域的超級(jí)域,則較短的域?qū)⒂糜诤罄m(xù)原始檢查。例如:

    假設(shè)文檔中的一個(gè)腳本在 http://store.company.com/dir/other.html 執(zhí)行以下語(yǔ)句:

    document.domain = "company.com";

    這條語(yǔ)句執(zhí)行之后,頁(yè)面將會(huì)成功地通過(guò)對(duì) http://company.com/dir/page.html 的同源檢測(cè)。而同理,company.com 不能設(shè)置 document.domain 為 othercompany.com.

  • 瀏覽器單獨(dú)保存端口號(hào)。任何的賦值操作,包括document.domain = document.domain都會(huì)以null值覆蓋掉原來(lái)的端口號(hào)。賦值時(shí)必須帶上端口號(hào),以確保端口號(hào)不會(huì)為null。

5.postMessage:

  • window.postMessage() 方法可以安全地實(shí)現(xiàn)跨源通信。當(dāng)且僅當(dāng)執(zhí)行它們的頁(yè)面位于具有相同的協(xié)議,端口號(hào)(443為https的默認(rèn)值),以及主機(jī)(模數(shù) Document.domain 由兩個(gè)頁(yè)面設(shè)置為相同的值)。

  • window.postMessage() 方法被調(diào)用時(shí),會(huì)在所有頁(yè)面腳本執(zhí)行完畢之后向目標(biāo)窗口派發(fā)一個(gè) MessageEvent 消息。 示例:

    a頁(yè)面:
    var ipt = document.querySelector('#ipt')
    ipt.addEventListener('input', function () {
      window.frames[0].postMessage(this.value, '*')
    })
    // 監(jiān)聽(tīng)其它頁(yè)面發(fā)送來(lái)的消息
    window.addEventListener('message', function (e) {
      ipt.value = e.data
    })
    b頁(yè)面:
    var ipt = document.querySelector('#ipt')
    
    ipt.addEventListener('input', function () {
      window.parent.postMessage(this.value, '*')
    })
    
    window.addEventListener('message', function (e) {
      ipt.value = e.data
    })
    

    完整示例

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
平臺(tái)聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點(diǎn),簡(jiǎn)書(shū)系信息發(fā)布平臺(tái),僅提供信息存儲(chǔ)服務(wù)。

推薦閱讀更多精彩內(nèi)容

  • 1. 什么是跨域? 跨域一詞從字面意思看,就是跨域名嘛,但實(shí)際上跨域的范圍絕對(duì)不止那么狹隘。具體概念如下:只要協(xié)議...
    他在發(fā)呆閱讀 829評(píng)論 0 0
  • 1. 什么是跨域? 跨域一詞從字面意思看,就是跨域名嘛,但實(shí)際上跨域的范圍絕對(duì)不止那么狹隘。具體概念如下:只要協(xié)議...
    w_zhuan閱讀 527評(píng)論 0 0
  • 跨域資源共享 CORS 對(duì)于web開(kāi)發(fā)來(lái)講,由于瀏覽器的同源策略,我們需要經(jīng)常使用一些hack的方法去跨域獲取資源...
    默默先生Alec閱讀 600評(píng)論 0 0
  • 什么是跨域? 2.) 資源嵌入:、、、等dom標(biāo)簽,還有樣式中background:url()、@font-fac...
    電影里的夢(mèng)i閱讀 2,383評(píng)論 0 5
  • Section1、為什么要跨域? 自古以來(lái)(1995年起),為了用戶的信息安全,瀏覽器就引入了同源策略。那么同源策...
    qhaobaba閱讀 391評(píng)論 0 0