日韩性视频-久久久蜜桃-www中文字幕-在线中文字幕av-亚洲欧美一区二区三区四区-撸久久-香蕉视频一区-久久无码精品丰满人妻-国产高潮av-激情福利社-日韩av网址大全-国产精品久久999-日本五十路在线-性欧美在线-久久99精品波多结衣一区-男女午夜免费视频-黑人极品ⅴideos精品欧美棵-人人妻人人澡人人爽精品欧美一区-日韩一区在线看-欧美a级在线免费观看

歡迎訪問 生活随笔!

生活随笔

當前位置: 首頁 > 前端技术 > HTML >内容正文

HTML

常用的前端跨域的几种方式

發布時間:2025/3/17 HTML 16 豆豆
生活随笔 收集整理的這篇文章主要介紹了 常用的前端跨域的几种方式 小編覺得挺不錯的,現在分享給大家,幫大家做個參考.

前端跨域

前端跨域有多少種情況

  • CORS 跨域
  • jsonp 跨域
  • postMessage
  • document.domain 一般情況下我們使用比較多的就是 Cross-Origin和 jsonp 這兩種方式。postMessage 和 document.domain 使用的不是很多。下面我會介紹他們如何使用和使用的場景還有一些不常見的問題。

CORS

全拼 cross-origin resource sharing,意思是跨域資源共享。我們先看看瀏覽器的兼容性,如下圖:

注意: 所以要使用 CORS 進行跨域的話,必須注意客戶端和服務器必須同時支持。

瀏覽器將 CORS 請求分成兩類:簡單請求(simple request)和非簡單請求(not-so-simple request),我們看看如何區分

1.請求方法是以下三種方法之一:

  • HEAD
  • GET
  • POST

2.HTTP的頭信息不超出以下幾種字段:

  • Accept
  • Accept-Language
  • Content-Language
  • Last-Event-ID
  • Content-Type :只限于三個值 application/x-www-form-urlencoded 、multipart/form-data、text/plain

簡單請求(simple request)

  • 對于簡單請求,瀏覽器直接發出CORS請求。具體來說,就是在頭信息之中,增加一個Origin字段。Origin字段用來說明,本次請求來自哪個源(協議 + 域名 + 端口)。服務器根據這個值,決定是否同意這次請求。

  • 如果 Origin 指定的源,不在許可范圍內,服務器會返回一個正常的 HTTP 回應。瀏覽器發現,這個回應的頭信息沒有包含 Access-Control-Allow-Origin 字段(詳見下文),就知道出錯了,從而拋出一個錯誤,被 XMLHttpRequest 的 onerror 回調函數捕獲。注意,這種錯誤無法通過狀態碼識別,因為 HTTP 回應的狀態碼有可能是200。(如果我們使用的 fetch,那么 fetch 會自動觸發一個錯誤,那么這個時候我們可以通過 promise.catch() 方法可捕獲這個錯誤信息)。

  • 如果 Origin 指定的域名在許可范圍內,服務器返回的響應,會多出幾個頭信息字段

// 該字段是必須的。它的值要么是請求時Origin字段的值,要么是一個*,表示接受任意域名的請求Access-Control-Allow-Origin: http://api.bob.com// 該字段可選。它的值是一個布爾值,表示是否允許發送Cookie,如果需要發送cookie那么就設置為true,否則不會含有這個字段// 如果要發送cookie,那么還需要設置 var xhr = new XMLHttpRequest(); xhr.withCredentials = true;Access-Control-Allow-Credentials: true// 該字段可選。CORS請求時,XMLHttpRequest對象的getResponseHeader()方法只能拿到6個基本字段:// Cache-Control、Content-Language、Content-Type、Expires、Last-Modified、Pragma// 如果想拿到其他字段,就必須在Access-Control-Expose-Headers里面指定。上面的例子指定// getResponseHeader('FooBar')可以返回FooBar字段的值。Access-Control-Expose-Headers: FooBar復制代碼

需要注意的是,如果要發送 Cookie,Access-Control-Allow-Origin就不能設為*,必須指定明確的、與請求網頁的域名一致。

非簡單請求(not-so-simple request)

  • 非簡單請求的 CORS 請求,會在正式通信之前,增加一次 HTTP 查詢請求,稱為 預檢請求(preflight)。

  • 預檢請求 用的請求方法是 OPTIONS,表示這個請求是用來詢問的。頭信息里面,關鍵字段是 Origin,表示請求來自哪個源。

  • 除了 Origin 字段,"預檢"請求的頭信息包括兩個特殊字段

// 該字段是必須的,用來列出瀏覽器的CORS請求會用到哪些HTTP方法,上例是PUT。Access-Control-Request-Method: PUT// 該字段是一個逗號分隔的字符串,指定瀏覽器CORS請求會額外發送的頭信息字段Access-Control-Request-Headers: X-Custom-Header復制代碼
  • 服務器收到預檢請求以后,檢查了 Origin、Request-Method 和 Request-Headers 字段以后,確認允許跨源請求,就可以做出回應。如果瀏覽器否定了"預檢"請求,會返回一個正常的 HTTP 回應,但是沒有任何 CORS 相關的頭信息字段。這時,瀏覽器就會認定,服務器不同意預檢請求,因此觸發一個錯誤,被 XMLHttpRequest 對象的 onerror 回調函數捕獲
// 該字段必需, 字段也可以設為星號,表示同意任意跨源請求Access-Control-Allow-Origin: *// 該字段必需,它的值是逗號分隔的一個字符串,表明服務器支持的所有跨域請求的方法。// 注意,返回的是所有支持的方法,而不單是瀏覽器請求的那個方法。這是為了避免多次"預檢"請求。Access-Control-Allow-Methods: GET, POST, PUT// 如果瀏覽器請求包括Access-Control-Request-Headers字段,則Access-Control-Allow-Headers字段是必需的。// 它也是一個逗號分隔的字符串,表明服務器支持的所有頭信息字段,不限于瀏覽器在"預檢"中請求的字段。Access-Control-Allow-Headers: X-Custom-Header// 該字段可選// 該字段與簡單請求時的含義相同Access-Control-Allow-Credentials: true// 該字段可選,用來指定本次預檢請求的有效期,單位為秒。// 即允許緩存該條回應1728000秒(即20天),在此期間,不用發出另一條預檢請求。Access-Control-Max-Age: 1728000復制代碼

一旦服務器通過了"預檢"請求,以后每次瀏覽器正常的 CORS 請求,就都跟簡單請求一樣,會有一個 Origin 頭信息字段。服務器的回應,也都會有一個 Access-Control-Allow-Origin 頭信息字段。

我們以 koa為列,在demo中這么設置就可以了

// 下面是對cors進行的設置,在返回的headers中添加如下字段,也可以使用 koa2-cors app.use(async (ctx, next) => {// 允許來自所有域名請求,請求攜帶了cookie就不能設置為 * ctx.set("Access-Control-Allow-Origin", "http://10.105.16.162:3000");// 設置所允許的HTTP請求方法ctx.set("Access-Control-Allow-Methods", "GET,POST");// 它也是一個逗號分隔的字符串,表明服務器支持的所有頭信息字段.ctx.set("Access-Control-Allow-Headers", "x-requested-with,accept,origin,content-type");// 該字段可選。它的值是一個布爾值,表示是否允許發送Cookie。默認情況下,Cookie不包括在CORS請求之中。// 當設置成允許請求攜帶cookie時,需要保證"Access-Control-Allow-Origin"是服務器有的域名,而不能是"*";ctx.set("Access-Control-Allow-Credentials", true);await next();}); 復制代碼

jonsp 跨域

jonsp跨域的原理是通過動態創建script的標簽的形式來實現跨域的,因為script不受同源策略的影響。但是jsonp只能接受get方法。 看看下面的代碼是如何封裝的,并做了超時設置。

const defaultOptions = {timeout: 15000,uid: 0,perfix: '_jsp',name: 'callBack', } const jsp = (url, params, options = {}) => {let timer = null;const options = Object.assign({}, defaultOptions, options);const callBackName = `${options.perfix}_${options.name}_${options.uid++}`;const paramsKeys = Object.entries(params);url += `?${callback}=${callBackName}`;url = paramsKeys.reduce((initUrl, [k, v]) => {return `${initUrl}&${k}=${v}`;}, url);const body = document.getElementByTagName(body)[0];const script = document.createElement('script');script.src = url;body.appendChild(script);const clean = () => {if (timer) {clearInterval(timer);timer = null;body.removeChild(script);window[callBackName] = null;}};return new Promise((resolve, reject) => {window[callBackName] = function(data) {clear();return resolve(data);};timer = setTimeout(() => {clear();return reject('請求超時了');}, options.time);}); }復制代碼

postMessage (這是HTML5提供的方法,IE8+才支持) 可以實現兩個窗口之間的通信,是不是同源不重要

它可用于解決以下方面的問題:

  • 頁面和其打開的新窗口的數據傳遞
  • 多窗口之間消息傳遞
  • 頁面與嵌套的iframe消息傳遞

使用方法:postMessage(data, origin) 方法接受兩個參數 data html5規范支持任意基本類型或可復制的對象,但部分瀏覽器只支持字符串,所以傳參時最好用 JSON.stringify()序列化。IE10才開始支持對象形式。 origin 協議+主機+端口號,也可以設置為 *,表示可以傳遞給任意窗口,如果要指定和當前窗口同源的話設置為 /。

// 發送窗口代碼:const ifr = document.createElement('iframe');ifr.src = 'http://localhost:3001';ifr.display = 'none';document.body.append(ifr);ifr.onload = function() {const doc = ifr.contentWindow;// 目標源 可以限定具體的 協議 + 域名 + 端口 或者是 *const targetOrigin = 'http://localhost:3001';// 發送消息 doc可以是window.open() 也可以是嵌套的iframe// 發送的消息可以是 string 或者 object(IE10才支持)doc.postMessage('hello world', targetOrigin);}// 接收窗口代碼:window.addEventListener('message', (e)=> { // 必須是window不能是document監聽// 數據const data = e.data;// 消息是從哪個源發送來的const origin = e.origin;// 發送消息窗口 const source = e.source;// 通過source回傳消息 同樣在發送消息的窗口也需要監聽source.postMessage('hi shenxuxiang', 'http://localhost:3000');},false)復制代碼

document.domain

此方案僅限主域相同,子域不同的跨域應用場景。實現原理:兩個頁面都通過js強制設置document.domain為基礎主域,就實現了同域。 之后就可以共享window下的屬性。

// www.a.com/a.html頁面中的代碼document.domain = 'a.com';const ifr = document.createElement('iframe');ifr.src = 'http://www.script.a.com/b.html';ifr.display = 'none';document.body.append(ifr);ifr.onload = function() {const doc = ifr.contentWindow;console.log(doc.name); // shenxuxiang}// www.script.a.com/b.html頁面中的代碼document.domain = 'a.com';window.name = 'shenxuxiang';復制代碼

上面一共介紹了4種前端跨域的方法,jsonp 和 cors 可以和后臺進行跨域,而 postMessage 和 domain 適合頁面間的通訊。頁面間的跨域還有可以使用 window.name | location.hash。如果想了解的可以點擊這里

參考

Cross-Origin Resource Sharing MDN

轉載于:https://juejin.im/post/5ceded75f265da1b5e72d4d3

總結

以上是生活随笔為你收集整理的常用的前端跨域的几种方式的全部內容,希望文章能夠幫你解決所遇到的問題。

如果覺得生活随笔網站內容還不錯,歡迎將生活随笔推薦給好友。