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

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

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

前言

什么是跨域問(wèn)題

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

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

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

https://192.168.31.45:8080/user

https://192.168.31.45:8080/list

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

跨域問(wèn)題的原因

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

JSONP

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

下面是 JSONP 解決跨域請(qǐng)求的基本原理:

  • 前端發(fā)起 JSONP 請(qǐng)求: 前端頁(yè)面通過(guò)動(dòng)態(tài)創(chuàng)建 <script> 標(biāo)簽,設(shè)置其 src 屬性為包含回調(diào)函數(shù)的 URL。通常這個(gè) URL 是指向另一個(gè)域名下的服務(wù)器接口。
  • 服務(wù)端返回?cái)?shù)據(jù): 服務(wù)端接收到 JSONP 請(qǐng)求后,會(huì)將數(shù)據(jù)包裝在回調(diào)函數(shù)中返回給前端。這樣前端頁(yè)面就可以獲得跨域請(qǐng)求返回的數(shù)據(jù)。
  • 前端處理數(shù)據(jù): 前端頁(yè)面定義好與回調(diào)函數(shù)同名的 JavaScript 函數(shù),當(dāng)服務(wù)端返回?cái)?shù)據(jù)時(shí),會(huì)執(zhí)行這個(gè)函數(shù)并傳入返回的數(shù)據(jù)作為參數(shù),從而實(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>
    // 定義一個(gè)函數(shù) jsonp,用于發(fā)送 JSONP 請(qǐng)求
    function jsonp(url, cb) {
      return new Promise((resolve, reject) => {
        // 創(chuàng)建一個(gè) script 標(biāo)簽
        const script = document.createElement('script');
        
        // 設(shè)置 script 的 src 屬性,包含了請(qǐng)求的 URL 和回調(diào)函數(shù)名稱(chēng)
        script.src = `${url}?cb=${cb}`; // http://localhost:3000?cb='callback'
        
        // 將 script 添加到文檔中
        document.body.appendChild(script); // 瀏覽器自動(dòng)請(qǐng)求 src 中的內(nèi)容
        
        // 定義一個(gè)全局函數(shù),用于處理返回的數(shù)據(jù)
        window[cb] = (data) => {
          resolve(data)
        }
      })
    }
    
    // 獲取按鈕元素
    let btn = document.getElementById('btn');
    
    // 綁定點(diǎn)擊事件
    btn.addEventListener('click', () => {
      // 發(fā)送 JSONP 請(qǐng)求
      jsonp('http://localhost:3000', 'callback')
      .then(res => {
        console.log('后端的返回結(jié)果:' + res);
      })

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

后端代碼:

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

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

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

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

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

優(yōu)點(diǎn):

  • 簡(jiǎn)單易用: JSONP 實(shí)現(xiàn)簡(jiǎn)單,只需在前端添加一個(gè) <script> 標(biāo)簽即可完成跨域請(qǐng)求,無(wú)需復(fù)雜的配置。
  • 兼容性好: JSONP 能夠兼容各種瀏覽器,包括早期版本的瀏覽器,因?yàn)樗峭ㄟ^(guò)動(dòng)態(tài)創(chuàng)建 <script> 標(biāo)簽實(shí)現(xiàn)的。
  • 支持跨域請(qǐng)求: JSONP 可以在不同域之間進(jìn)行數(shù)據(jù)通信,解決了傳統(tǒng) AJAX 請(qǐng)求受同源策略限制的問(wèn)題。

缺點(diǎn):

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

CORS(跨域資源共享)

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

前端代碼:在用戶(hù)點(diǎn)擊按鈕時(shí),通過(guò)發(fā)送跨域請(qǐng)求獲取服務(wù)器返回的數(shù)據(jù),并將數(shù)據(jù)打印到瀏覽器的控制臺(tái)

<!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ā)送跨域請(qǐng)求到服務(wù)器
      .then(res => res.json())
      .then((res) => {
        console.log(res);  // 打印返回的數(shù)據(jù)到控制臺(tái)
      })
    })

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

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

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

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

const http = require('http');

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

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

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

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

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

  • Access-Control-Allow-Origin:指定允許訪問(wèn)的域名。

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

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

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

  • Access-Control-Allow-Headers:指定允許的自定義請(qǐng)求頭。

CORS支持各種類(lèi)型的HTTP請(qǐng)求,包括GET、POST等。

domain

我們還可以使用 Domain 方法來(lái)解決一些特定情況下的跨域訪問(wèn)問(wèn)題。 在跨域通信時(shí),還需要注意以下幾點(diǎn):

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

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

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

下面舉一個(gè)簡(jiǎn)單的例子來(lái)說(shuō)明 Domain 方法的用法:

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

在父級(jí)頁(yè)面 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>

在子級(jí)頁(yè)面 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!';
    
    // 訪問(wèn)父級(jí)頁(yè)面定義的變量
    var message = window.parent.messageFromParent;
    console.log('Message from parent: ' + message);
  </script>
</body>
</html>

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

父級(jí)頁(yè)面定義了一個(gè)名為 messageFromParent 的變量,子級(jí)頁(yè)面在加載后通過(guò) window.parent 來(lái)訪問(wèn)父級(jí)頁(yè)面定義的變量,并打印出父級(jí)頁(yè)面的消息。

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

postMessage

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

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

在 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)建一個(gè) iframe 元素來(lái)加載 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() {
      // 準(zhǔn)備要發(fā)送的數(shù)據(jù)
      let data = {
        name: 'Tom'
      };
      // 通過(guò) postMessage 方法向 iframe 發(fā)送數(shù)據(jù)
      iframe.contentWindow.postMessage(JSON.stringify(data), 'http://127.0.0.1:5500');
    }

    // 監(jiān)聽(tīng)來(lái)自 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)聽(tīng)來(lái)自父頁(yè)面的消息
    window.addEventListener('message', function(e) {
      console.log(JSON.parse(e.data));

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

優(yōu)點(diǎn):

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

缺點(diǎn):

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

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

相關(guān)文章

  • JavaScript實(shí)現(xiàn)隨機(jī)點(diǎn)名小程序

    JavaScript實(shí)現(xiàn)隨機(jī)點(diǎn)名小程序

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

    躲避這些會(huì)改變?cè)瓟?shù)組JavaScript數(shù)組方法讓開(kāi)發(fā)流暢無(wú)阻

    JavaScript中有些數(shù)組的操作方法并不符合我們預(yù)期,容易導(dǎo)致想象不到的結(jié)果,因此,為避免這種情況的發(fā)生,本文將介紹哪些原生數(shù)組方法能改變?cè)瓟?shù)組以及我對(duì)于如何更好地使用數(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一個(gè)很大的區(qū)別就是具有響應(yīng)式,需要的朋友可以參考下
    2023-10-10
  • JavaScript庫(kù) 開(kāi)發(fā)規(guī)則

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

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

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

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

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

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

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

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

    簡(jiǎn)單談?wù)刯avascript Date類(lèi)型

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

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

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

    JS簡(jiǎn)單判斷是否在微信瀏覽器打開(kāi)的方法示例

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

最新評(píng)論