欧美bbbwbbbw肥妇,免费乱码人妻系列日韩,一级黄片

JavaScript解決跨域的三種方法小結(jié)

 更新時間:2024年03月14日 09:03:13   作者:好好吃飯e  
在Web應(yīng)用中,當(dāng)一個網(wǎng)頁的腳本試圖去請求另一個域名下的資源時,就會遇到跨域問題,跨域問題是由瀏覽器的同源策略所引起的,本文給大家介紹了JavaScript解決跨域的三種方法,需要的朋友可以參考下

前言

什么是跨域問題

在Web應(yīng)用中,當(dāng)一個網(wǎng)頁的腳本試圖去請求另一個域名下的資源時,就會遇到跨域問題。跨域問題是由瀏覽器的同源策略所引起的。換句話說:后端返回給瀏覽器的數(shù)據(jù)會被瀏覽器的同源策略給攔截下來。

同源策略要求資源的協(xié)議、域名和端口號都必須相同,才能確保數(shù)據(jù)的安全性。如果不滿足這個條件,請求將被瀏覽器拒絕,從而導(dǎo)致跨域問題的出現(xiàn)。

  • 同源策略: 協(xié)議號-域名-端口號 都相同的地址,瀏覽器才認為是同源
協(xié)議號:域名:端口號 / 路徑

https://192.168.31.45:8080/user

https://192.168.31.45:8080/list

上面這個例子雖然它們的路徑不一樣但是協(xié)議號、域名、端口號都相同,所以它們就是同源的

跨域問題的原因

跨域問題主要是由于瀏覽器的安全策略限制引起的。同源策略的目的是保護用戶的隱私和數(shù)據(jù)安全,防止惡意網(wǎng)站獲取用戶的敏感信息或進行未授權(quán)的操作。 通過限制跨域請求,瀏覽器有效地減少了許多網(wǎng)絡(luò)攻擊的風(fēng)險,例如跨站腳本攻擊(XSS)和跨站請求偽造(CSRF)。

JSONP

JSONP(JSON with Padding)是一種用于解決跨域請求的技術(shù),它利用了 <script> 標簽可以跨域加載資源的特性。

下面是 JSONP 解決跨域請求的基本原理:

  • 前端發(fā)起 JSONP 請求: 前端頁面通過動態(tài)創(chuàng)建 <script> 標簽,設(shè)置其 src 屬性為包含回調(diào)函數(shù)的 URL。通常這個 URL 是指向另一個域名下的服務(wù)器接口。
  • 服務(wù)端返回數(shù)據(jù): 服務(wù)端接收到 JSONP 請求后,會將數(shù)據(jù)包裝在回調(diào)函數(shù)中返回給前端。這樣前端頁面就可以獲得跨域請求返回的數(shù)據(jù)。
  • 前端處理數(shù)據(jù): 前端頁面定義好與回調(diào)函數(shù)同名的 JavaScript 函數(shù),當(dāng)服務(wù)端返回數(shù)據(jù)時,會執(zhí)行這個函數(shù)并傳入返回的數(shù)據(jù)作為參數(shù),從而實現(xiàn)跨域數(shù)據(jù)的獲取和處理。

前端代碼:

<!DOCTYPE html>
<html lang="en">
<head>
  <meta charset="UTF-8">
  <meta name="viewport" content="width=device-width, initial-scale=1.0">
  <title>Document</title>
</head>
<body>
  <button id="btn">獲取數(shù)據(jù)</button>
  <script>
    // 定義一個函數(shù) jsonp,用于發(fā)送 JSONP 請求
    function jsonp(url, cb) {
      return new Promise((resolve, reject) => {
        // 創(chuàng)建一個 script 標簽
        const script = document.createElement('script');
        
        // 設(shè)置 script 的 src 屬性,包含了請求的 URL 和回調(diào)函數(shù)名稱
        script.src = `${url}?cb=${cb}`; // http://localhost:3000?cb='callback'
        
        // 將 script 添加到文檔中
        document.body.appendChild(script); // 瀏覽器自動請求 src 中的內(nèi)容
        
        // 定義一個全局函數(shù),用于處理返回的數(shù)據(jù)
        window[cb] = (data) => {
          resolve(data)
        }
      })
    }
    
    // 獲取按鈕元素
    let btn = document.getElementById('btn');
    
    // 綁定點擊事件
    btn.addEventListener('click', () => {
      // 發(fā)送 JSONP 請求
      jsonp('http://localhost:3000', 'callback')
      .then(res => {
        console.log('后端的返回結(jié)果:' + res);
      })

    })
  </script>
</body>
</html>

后端代碼:

const Koa = require('koa');
const app = new Koa();

// 定義中間件函數(shù) main,處理請求并返回數(shù)據(jù)
const main = (ctx, next) => {
  console.log(ctx.query); // 輸出請求參數(shù)對象 { cb: 'callback' }
  
  // 從請求參數(shù)中獲取回調(diào)函數(shù)名稱
  const cb = ctx.query.cb;

  // 準備要返回給前端的數(shù)據(jù)
  const data = '給前端的數(shù)據(jù)';
  
  // 構(gòu)造帶有回調(diào)函數(shù)名稱的字符串,格式為 'callback("給前端的數(shù)據(jù)")'
  const str = `${cb}('${data}')`;
  
  // 將構(gòu)造好的字符串作為響應(yīng)體返回給前端
  ctx.body = str;
}

// 將 main 中間件注冊到 Koa 應(yīng)用中
app.use(main);

// 監(jiān)聽 3000 端口,啟動服務(wù)器
app.listen(3000, () => {
  console.log('listening on port 3000');
})

優(yōu)點:

  • 簡單易用: JSONP 實現(xiàn)簡單,只需在前端添加一個 <script> 標簽即可完成跨域請求,無需復(fù)雜的配置。
  • 兼容性好: JSONP 能夠兼容各種瀏覽器,包括早期版本的瀏覽器,因為它是通過動態(tài)創(chuàng)建 <script> 標簽實現(xiàn)的。
  • 支持跨域請求: JSONP 可以在不同域之間進行數(shù)據(jù)通信,解決了傳統(tǒng) AJAX 請求受同源策略限制的問題。

缺點:

  • 安全性問題: JSONP 存在安全風(fēng)險,因為它是通過在前端動態(tài)加載腳本來獲取數(shù)據(jù),可能會被用于注入惡意腳本,導(dǎo)致安全漏洞。
  • 只支持 GET 請求: JSONP 只能發(fā)起 GET 請求,無法支持其他類型的 HTTP 請求,如 POST、PUT 等。
  • 依賴服務(wù)端支持: JSONP 需要服務(wù)端返回數(shù)據(jù)時將其包裹在一個回調(diào)函數(shù)中,因此需要服務(wù)端提供支持,如果服務(wù)端不支持 JSONP 格式返回數(shù)據(jù),則無法使用該方法。

CORS(跨域資源共享)

CORS是一種機制,允許服務(wù)器在響應(yīng)中攜帶一個特殊的標頭,以告知瀏覽器該服務(wù)器允許哪些源的網(wǎng)頁訪問其資源。 可以總結(jié)為一句話:后端通過設(shè)置響應(yīng)頭來告訴瀏覽器不要拒絕接受后端的響應(yīng)。

前端代碼:在用戶點擊按鈕時,通過發(fā)送跨域請求獲取服務(wù)器返回的數(shù)據(jù),并將數(shù)據(jù)打印到瀏覽器的控制臺

<!DOCTYPE html>
<html lang="en">
<head>
  <meta charset="UTF-8">
  <meta name="viewport" content="width=device-width, initial-scale=1.0">
  <title>Document</title>
</head>
<body>
  <button id="btn">獲取數(shù)據(jù)</button>

  <script>
    let btn = document.getElementById('btn');
    btn.addEventListener('click', () => {
      fetch('http://localhost:3000')  // 發(fā)送跨域請求到服務(wù)器
      .then(res => res.json())
      .then((res) => {
        console.log(res);  // 打印返回的數(shù)據(jù)到控制臺
      })
    })

  </script>
</body>
</html>

代碼實現(xiàn)了以下功能:

  • 在 HTML 中定義了一個按鈕元素,id 為 "btn",用于觸發(fā)發(fā)送數(shù)據(jù)請求。
  • 在 JavaScript 部分,使用 fetch 函數(shù)發(fā)送 GET 請求到指定的服務(wù)器地址 "http://localhost:3000"。
  • 在成功接收到服務(wù)器響應(yīng)后,使用 .then 方法將響應(yīng)解析為 JSON 格式。
  • 在第二個 .then 方法中,處理解析后的數(shù)據(jù),并將其輸出到瀏覽器的控制臺。

后端代碼 :Node.js 服務(wù)器代碼,創(chuàng)建了一個 HTTP 服務(wù)器,監(jiān)聽在端口 3000。當(dāng)接收到請求時,返回一個包含 "hello cors" 消息的 JSON 數(shù)據(jù)。

const http = require('http');

const server = http.createServer((req, res) => {
  res.writeHead(200, {
     // cros實現(xiàn)原理
    'Access-Control-Allow-Origin': 'http://127.0.0.1:5500'  // 允許來自指定地址的跨域請求
  })

  let data = {
    msg: "hello cors"
  }
  res.end(JSON.stringify(data)) // 返回數(shù)據(jù)給前端頁面
})

server.listen(3000, () => {
  console.log('listening on port 3000');
})

后端代碼第6行在服務(wù)端設(shè)置響應(yīng)頭來控制跨域訪問。

常見的響應(yīng)頭包括:

  • Access-Control-Allow-Origin:指定允許訪問的域名。

  • 例如,Access-Control-Allow-Origin: *表示允許所有域名訪問,

  • Access-Control-Allow-Origin:'http://127.0.0.1:5500'表示只允許特定域名訪問。

  • Access-Control-Allow-Methods:指定允許的HTTP方法。

  • Access-Control-Allow-Headers:指定允許的自定義請求頭。

CORS支持各種類型的HTTP請求,包括GET、POST等。

domain

我們還可以使用 Domain 方法來解決一些特定情況下的跨域訪問問題。 在跨域通信時,還需要注意以下幾點:

  • 頁面的域名必須滿足 Domain 方法的限制,即二級域名相同(如 example.com)。

  • 父級頁面需要在設(shè)置 document.domain 之前定義需要共享的變量或?qū)ο蟆?/p>

  • 子級頁面可以通過 window.parent 來訪問父級頁面的屬性或變量,但需要確保父級頁面已經(jīng)加載完成并且兩者的域名設(shè)置已生效。

下面舉一個簡單的例子來說明 Domain 方法的用法:

假設(shè)有兩個頁面分別位于不同子域名下,一個是 parent.example.com,另一個是 child.example.com。我們希望這兩個頁面能夠進行跨域通信。

在父級頁面 parent.example.com/index.html 中的代碼如下:

<!DOCTYPE html>
<html lang="en">
<head>
  <meta charset="UTF-8">
  <meta name="viewport" content="width=device-width, initial-scale=1.0">
  <title>Parent Page</title>
</head>
<body>
  <h1>Parent Page</h1>
  <iframe src="http://child.example.com/child.html"></iframe>
  
  <script>
    document.domain = 'example.com';
    var messageFromParent = 'Hello from parent page!';
  </script>
</body>
</html>

在子級頁面 child.example.com/child.html 中的代碼如下:

<!DOCTYPE html>
<html lang="en">
<head>
  <meta charset="UTF-8">
  <meta name="viewport" content="width=device-width, initial-scale=1.0">
  <title>Child Page</title>
</head>
<body>
  <h1>Child Page</h1>
  
  <script>
    document.domain = 'example.com';
    var messageFromChild = 'Hello from child page!';
    
    // 訪問父級頁面定義的變量
    var message = window.parent.messageFromParent;
    console.log('Message from parent: ' + message);
  </script>
</body>
</html>

在這個例子中,父級頁面和子級頁面分別設(shè)置了相同的 document.domain 為 'example.com',以實現(xiàn)二級域名相同。

父級頁面定義了一個名為 messageFromParent 的變量,子級頁面在加載后通過 window.parent 來訪問父級頁面定義的變量,并打印出父級頁面的消息。

通過設(shè)置相同的 document.domain,父子頁面之間就可以進行跨域通信,實現(xiàn)數(shù)據(jù)共享和交互。

postMessage

使用 postMessage() 方法結(jié)合 <iframe> 元素可以實現(xiàn)跨域通信,這是一種常見的技術(shù)。通過在父窗口和嵌套的 <iframe> 之間使用 postMessage() 方法,可以安全地在不同源之間進行通信。

<iframe> 可以用于解決跨域通信的問題,其原理是利用瀏覽器中同源策略的限制,將不同域的內(nèi)容加載到獨立的 <iframe> 中,通過 postMessage 方法進行跨文檔通信。

在 a.html 文件中:

<!DOCTYPE html>
<html lang="en">
<head>
  <meta charset="UTF-8">
  <meta name="viewport" content="width=device-width, initial-scale=1.0">
  <title>Document</title>
</head>
<body>
  <h2>a.html</h2>

  <!-- 創(chuàng)建一個 iframe 元素來加載 b.html -->
  <iframe src="http://127.0.0.1:5500/postMessage/b.html" frameborder="0" id="iframe"></iframe>

  <script>
    // 向 b.html 發(fā)送數(shù)據(jù)
    let iframe = document.getElementById('iframe');
    iframe.onload = function() {
      // 準備要發(fā)送的數(shù)據(jù)
      let data = {
        name: 'Tom'
      };
      // 通過 postMessage 方法向 iframe 發(fā)送數(shù)據(jù)
      iframe.contentWindow.postMessage(JSON.stringify(data), 'http://127.0.0.1:5500');
    }

    // 監(jiān)聽來自 b.html 的消息
    window.addEventListener('message', function(e) {
      console.log(e.data);
    });
  </script>
</body>
</html>

在 b.html 文件中:

<!DOCTYPE html>
<html lang="en">
<head>
  <meta charset="UTF-8">
  <meta name="viewport" content="width=device-width, initial-scale=1.0">
  <title>Document</title>
</head>
<body>
  <h4>b.html</h4>

  <script>
    // 監(jiān)聽來自父頁面的消息
    window.addEventListener('message', function(e) {
      console.log(JSON.parse(e.data));

      if (e.data) {
        // 收到消息后延遲 2 秒發(fā)送回應(yīng)給父頁面
        setTimeout(function() {
          window.parent.postMessage('我接受到', 'http://127.0.0.1:5500');
        }, 2000);
      }
    });
  </script>
</body>
</html>

優(yōu)點:

  • 安全性:  使用 <iframe> 結(jié)合 postMessage 進行跨域通信是一種相對安全的方法,能夠避免常見的跨站腳本攻擊(XSS)。
  • 靈活性:  可以在不同域之間傳遞數(shù)據(jù),實現(xiàn)更豐富的交互體驗,如單點登錄、共享數(shù)據(jù)等。
  • 適用性廣泛:  跨域通信是 Web 開發(fā)中常見需求,而 <iframe> 結(jié)合 postMessage 是一種通用且有效的解決方案。

缺點:

  • 復(fù)雜性:  跨域通信涉及到多個文檔之間的交互,需要額外的處理和編碼,增加了開發(fā)的復(fù)雜度。
  • 性能開銷:  使用 <iframe> 進行跨域通信可能會引入額外的網(wǎng)絡(luò)請求和資源加載,對頁面加載性能有一定影響。
  • 兼容性:  舊版本的瀏覽器可能對 postMessage 支持不完整,需要做兼容性處理。

以上就是JavaScript解決跨域的三種方法的詳細內(nèi)容,更多關(guān)于JavaScript解決跨域的資料請關(guān)注腳本之家其它相關(guān)文章!

相關(guān)文章

  • JavaScript實現(xiàn)隨機點名小程序

    JavaScript實現(xiàn)隨機點名小程序

    這篇文章主要介紹了JavaScript實現(xiàn)隨機點名小程序,文中示例代碼介紹的非常詳細,具有一定的參考價值,感興趣的小伙伴們可以參考一下
    2020-10-10
  • 躲避這些會改變原數(shù)組JavaScript數(shù)組方法讓開發(fā)流暢無阻

    躲避這些會改變原數(shù)組JavaScript數(shù)組方法讓開發(fā)流暢無阻

    JavaScript中有些數(shù)組的操作方法并不符合我們預(yù)期,容易導(dǎo)致想象不到的結(jié)果,因此,為避免這種情況的發(fā)生,本文將介紹哪些原生數(shù)組方法能改變原數(shù)組以及我對于如何更好地使用數(shù)組方法的建議
    2023-05-05
  • uni-app中px與rpx的轉(zhuǎn)換方法

    uni-app中px與rpx的轉(zhuǎn)換方法

    這篇文章主要給大家介紹了關(guān)于uni-app中px與rpx的轉(zhuǎn)換方法,rpx單位最初由微信推出,它與我們常用px一個很大的區(qū)別就是具有響應(yīng)式,需要的朋友可以參考下
    2023-10-10
  • JavaScript庫 開發(fā)規(guī)則

    JavaScript庫 開發(fā)規(guī)則

    1. 保持無侵入性,標記不想知道你的JavaScript代碼;2. 嚴禁修改和擴展Object.prototype!;3. 對JavaScript內(nèi)建對象的擴展越少越好;4. 跟隨標準;5. 或著跟隨主導(dǎo) ;6. 保持靈活;7. 管理內(nèi)存;8. 淘汰瀏覽器嗅探;9. 小巧更佳……
    2009-01-01
  • 22種JavaScript中數(shù)組常用API總結(jié)

    22種JavaScript中數(shù)組常用API總結(jié)

    在前端開發(fā)中,數(shù)組是一種常見且重要的數(shù)據(jù)結(jié)構(gòu),本文主要介紹了前端中數(shù)組常用的API,包括添加、刪除、截取、合并、轉(zhuǎn)換等操作,希望對大家有所幫助
    2023-05-05
  • 小程序異步問題之多個網(wǎng)絡(luò)請求依次執(zhí)行并依次收集請求結(jié)果

    小程序異步問題之多個網(wǎng)絡(luò)請求依次執(zhí)行并依次收集請求結(jié)果

    這篇文章主要介紹了小程序異步問題之多個網(wǎng)絡(luò)請求依次執(zhí)行并依次收集請求結(jié)果,小編覺得挺不錯的,現(xiàn)在分享給大家,也給大家做個參考。一起跟隨小編過來看看吧
    2019-05-05
  • JavaScript使用FileSystemObject對象寫入文本文件內(nèi)容的方法

    JavaScript使用FileSystemObject對象寫入文本文件內(nèi)容的方法

    這篇文章主要介紹了JavaScript使用FileSystemObject對象寫入文本文件內(nèi)容的方法,實例分析了javascript使用ActiveXObject的技巧與常見問題的解決方法,具有一定參考借鑒價值,需要的朋友可以參考下
    2015-08-08
  • 簡單談?wù)刯avascript Date類型

    簡單談?wù)刯avascript Date類型

    Date對象,是操作日期和時間的對象。Date對象對日期和時間的操作只能通過方法。本文就給大家簡單講述一下DATE類型的使用。
    2015-09-09
  • JS更改select內(nèi)option屬性的方法

    JS更改select內(nèi)option屬性的方法

    這篇文章主要介紹了JS更改select內(nèi)option屬性的方法,涉及JavaScript動態(tài)操作頁面select元素屬性的相關(guān)技巧,具有一定參考借鑒價值,需要的朋友可以參考下
    2015-10-10
  • JS簡單判斷是否在微信瀏覽器打開的方法示例

    JS簡單判斷是否在微信瀏覽器打開的方法示例

    這篇文章主要介紹了JS簡單判斷是否在微信瀏覽器打開的方法,結(jié)合實例形式分析了javascript針對瀏覽器相關(guān)信息的獲取與判定操作技巧,需要的朋友可以參考下
    2019-01-01

最新評論