js -- 跨域問題

丶Serendipity丶發表於2022-05-09

 

前言

  出於瀏覽器同源策略的影響,瀏覽器會阻止一個域的 js 指令碼和另一個域的內容進行互動,因此產生了跨域問題,該問題也經常在面試和開發中遇到,本文來總結一下相關知識點。

正文

  1、什麼是同源策略

  因為瀏覽器出於安全考慮,存在同源策略,就是說如果協議、域名、埠號有一個不同就產生了跨域,不同域之間的資源是不能互動的,比如:Ajax 請求別的域的資源就會失敗,無法讀取別的域中網頁的 Cookie 、LocalStorage 和 IndexedDB,無法獲取別的域中網頁中的 DOM 物件等。下面總結了跨域常見的解決方法。

  2、跨域解決方法

  (1)JSONP 解決跨域

  JSONP 是伺服器與客戶端跨源通訊的常用方法。最大特點就是簡單適用,相容性好(相容低版本IE),缺點是隻支援get請求,不支援post請求。

核心思想:網頁通過新增一個<script>元素,向伺服器請求 JSON 資料,伺服器收到請求後,將資料放在一個指定名字的回撥函式的引數位置傳回來。

  <script type="text/javascript">
    // 建立jsonp 函式
    function jsonp(url, data, callback) {
      var id = "_" + "Json" + (new Date()).getTime();  //建立一個幾乎唯一的id
      window[id] = function (result) {
        if (callback) {
          callback(result);
        }
        var getId = document.getElementById(id);  //移除Script標籤和id
        getId.parentNode.removeChild(getId);
        window[getId] = null;  //呼叫函式後進行銷燬
      }
      url = url.replace("callback=?", "callback=" + id);
      const script = document.createElement('script')
      script.src = url
      script.id = id
      script.async = true
      script.type = 'text/javascript'
      document.body.appendChild(script)
    }
    // 建立回撥函式
    function dosomething(res) {
      console.log(res.data)
    }
    // 呼叫jsonp函式
    jsonp('http://test.com/api/getInfo?callback=?', dosomething)
  </script>

  (2)document.domain 解決跨域

  瀏覽器通過 document.domain 屬性來判斷兩個頁面是否同源,因此可以設定相同的 document.domain 屬性值來解決跨域,缺點該方法只限於主域相同,子域不同的跨域場景。

    // a.html
    document.domain = "test.com"
    // b.html
    document.domain = "test.com"

  (3)postMessage Api 解決跨域

  通常用於獲取嵌入頁面中的第三方資料,一個頁面傳送訊息,另一個頁面接收訊息,比如通過 iframe 標籤嵌入的父子頁面之間的訊息傳值。

    <!-- 父頁面 -->
    <iframe src="child.html" frameborder="0" id="Iframe"></iframe>
    <script>
      // 監聽子頁面傳遞的值
      window.addEventListener('message', function (event) {
        
      })
      // 給子頁面發訊息
      document.getElementById('Iframe').contentWindow.postMessage(message, "*")
    </script>
    <!-- 子頁面 -->
    <script>
      // 子頁面給父頁面發訊息
       window.parent.postMessage("給父頁面發訊息", '*')
      //  監聽父頁面的訊息
       window.addEventListener('message', function (event) {
      })
    </script>

  (4)CORS 解決跨域

  該方式需要服務端和瀏覽器同時支援,瀏覽器會自動進行 CORS 通訊,後端實現了 CORS 就實現了跨域,服務端需要設定 Access-Control-Allow-Origin 就可以開啟 CORS ,該屬性表示哪些域名可以訪問資源,如果使用萬用字元則表示所有網站都可以訪問。

  如果要實現帶 Cookie 進行跨域請求,前端需要額外設定 withCredentials 為 true。

  (5)Nginx 反向代理

  該方法需要通過 Nginx 搭建中轉伺服器,用於轉發請求。只需要在 nginx.config 中配置轉發請求即可。

  (6)webpack-dev-server 設定本地代理

  該方式用於開發環境中,在webpack.config.js 中設定代理的本地伺服器就可以,如下:

devServer: {
        port: 8080,
        proxy: {
            "/api": {
              target: "http://192.168.25.20:8088" // 後端介面
            }
        }
    }

寫在最後

  以上就是本文的全部內容,希望給讀者帶來些許的幫助和進步,方便的話點個關注,小白的成長之路會持續更新一些工作中常見的問題和技術點。

 

 

 

 

相關文章