目錄
什么是跨域
概念
同源策略及限制內(nèi)容
常見(jiàn)跨域場(chǎng)景
如何解決跨域
CORS
Nginx代理跨域
Node中間件代理跨域
WebSocket
postMessage
JSONP
其他
什么是跨域
概念
在此之前,我們了解一下一個(gè)域名地址的組成:
跨域指的是在網(wǎng)絡(luò)安全中,由于瀏覽器的同源策略(Same-Origin Policy)限制,當(dāng)一個(gè)網(wǎng)頁(yè)的協(xié)議、域名或端口與另一個(gè)網(wǎng)頁(yè)的協(xié)議、域名或端口不同時(shí),就存在跨域問(wèn)題。如果缺少同源策略的限制,可能會(huì)導(dǎo)致安全隱患,如跨站腳本攻擊(XSS)或跨站請(qǐng)求偽造(CSRF)等。
同源策略及限制內(nèi)容
同源策略是瀏覽器的一項(xiàng)安全機(jī)制,它限制了來(lái)自不同源的腳本對(duì)當(dāng)前文檔的訪問(wèn)。同源策略要求資源必須來(lái)自同一個(gè)源(即協(xié)議、域名和端口相同),并限制了對(duì)以下內(nèi)容的訪問(wèn):
-
Cookie、LocalStorage、IndexedDB?等存儲(chǔ)性內(nèi)容:不允許在不同源之間讀取或?qū)懭脒@些數(shù)據(jù)。
-
DOM 節(jié)點(diǎn):不允許獲取來(lái)自不同源的 DOM 元素。
-
AJAX 請(qǐng)求發(fā)送后的響應(yīng)數(shù)據(jù):如果發(fā)起了跨域的 AJAX 請(qǐng)求,瀏覽器會(huì)阻止讀取其響應(yīng)內(nèi)容。
但是有三個(gè)標(biāo)簽允許跨域加載資源,它們不受同源策略限制:
<img src=XXX>
<link href=XXX>
<script src=XXX>
常見(jiàn)跨域場(chǎng)景
跨域存在于協(xié)議、子域名、主域名、端口號(hào)中任何一個(gè)不相同時(shí)。即使兩個(gè)不同的域名指向同一個(gè) IP 地址,只要其中任何一部分不同,就被視為不同源。
兩個(gè)重要點(diǎn):
- 協(xié)議和端口造成的跨域問(wèn)題需要后端處理,前端無(wú)法解決。
- 瀏覽器在判斷跨域時(shí)主要依據(jù) URL 的首部,即協(xié)議、域名和端口必須匹配。
跨域并不是指請(qǐng)求發(fā)不出去,而是瀏覽器限制了讀取來(lái)自其他域名下內(nèi)容的安全策略。例如,Ajax 請(qǐng)求會(huì)被瀏覽器攔截響應(yīng)數(shù)據(jù),但表單提交不會(huì)獲取新內(nèi)容,所以可以發(fā)起跨域請(qǐng)求。同樣,跨域并不能完全阻止 CSRF,因?yàn)檎?qǐng)求依然會(huì)發(fā)送出去,只是瀏覽器會(huì)攔截響應(yīng)。
如何解決跨域
CORS
CORS 通信過(guò)程都是瀏覽器自動(dòng)完成,需要瀏覽器(都支持)和服務(wù)器都支持,所以關(guān)鍵在只要服務(wù)器支持,就可以跨域通信,CORS請(qǐng)求分兩類:簡(jiǎn)單請(qǐng)求和非簡(jiǎn)單請(qǐng)求。
CORS請(qǐng)求默認(rèn)不包含Cookie以及HTTP認(rèn)證信息,如果需要包含Cookie,涉及跨域請(qǐng)求攜帶 Cookie 信息時(shí)需要一些特殊設(shè)置,其中涉及到 CORS 的頭部設(shè)置以及前端代碼的配置。
假設(shè)有兩個(gè)域名:https://example.com
?和?https://api.example.com
,前者是網(wǎng)頁(yè)的域名,后者是提供 API 的域名。下面是一個(gè)示例,演示如何設(shè)置跨域請(qǐng)求以在包含 Cookie 的情況下進(jìn)行:
后端設(shè)置 CORS 頭部
在 API 的響應(yīng)中設(shè)置 CORS 相關(guān)頭部:
// Express 示例
const express = require('express');
const app = express();
// 設(shè)置允許跨域請(qǐng)求的域名和允許攜帶 Cookie
app.use((req, res, next) => {
res.header('Access-Control-Allow-Origin', 'https://example.com');
res.header('Access-Control-Allow-Credentials', 'true');
next();
});
// 處理其他路由或請(qǐng)求
// ...
app.listen(3000);
前端發(fā)送帶有 withCredentials 的請(qǐng)求
在前端,如果想要在跨域請(qǐng)求中攜帶 Cookie,需要在 XMLHttpRequest 或 Fetch 請(qǐng)求中設(shè)置?withCredentials
?為?true
:
使用 XMLHttpRequest 的示例:
const xhr = new XMLHttpRequest();
xhr.open('GET', 'https://api.example.com/data', true);
xhr.withCredentials = true; // 允許攜帶 Cookie
xhr.send();
或者使用 Fetch API:
fetch('https://api.example.com/data', {
method: 'GET',
credentials: 'include', // 允許攜帶 Cookie
});
上述代碼中的關(guān)鍵點(diǎn)在于將 withCredentials 或 credentials: 'include' 設(shè)置為 true,這樣瀏覽器就會(huì)在請(qǐng)求中包含當(dāng)前頁(yè)面的 Cookie 信息。但要確保后端 API 設(shè)置了正確的 Access-Control-Allow-Origin 和 Access-Control-Allow-Credentials 頭部,并且不要使用 * 通配符,而是指定了明確的允許跨域的域名。
簡(jiǎn)單請(qǐng)求
簡(jiǎn)單請(qǐng)求指的是符合一定條件的跨域請(qǐng)求類型,在這種請(qǐng)求下,瀏覽器會(huì)自動(dòng)在頭部中添加 Origin 字段,表示請(qǐng)求的來(lái)源域,服務(wù)器根據(jù)這個(gè)來(lái)源決定是否允許請(qǐng)求。滿足以下兩個(gè)條件之一的請(qǐng)求被認(rèn)為是簡(jiǎn)單請(qǐng)求:
1.請(qǐng)求方法是?HEAD、GET、POST?之一
2.請(qǐng)求頭信息不超過(guò)一定限制。允許的請(qǐng)求頭包括:
-
Accept
-
Accept-Language
-
Content-Language
-
Last-Event-Id
-
Content-Type:允許的值為 application/x-www/form/urlencoded、multipart/form-data、text/plain 之一。
這些條件主要為了兼容早期的表單提交方式,因?yàn)闅v史上表單提交一直可以跨域。
在這樣的簡(jiǎn)單跨域請(qǐng)求中,服務(wù)器至少需要設(shè)置?Access-Control-Allow-Origin
?頭部來(lái)允許特定來(lái)源的請(qǐng)求。如果服務(wù)器認(rèn)可請(qǐng)求,會(huì)在響應(yīng)中返回以下必要的 CORS 頭部:
Access-Control-Allow-Origin | 這個(gè)字段是必須的,它指定了允許訪問(wèn)的來(lái)源域,一般是請(qǐng)求中 Origin 字段的值,但也可以是通配符 *,表示允許任意來(lái)源。 |
Access-Control-Allow-Credentials | 這個(gè)字段是可選的,表示是否允許發(fā)送 Cookie。如果需要跨域請(qǐng)求攜帶身份憑證(比如 Cookie 或 HTTP 認(rèn)證信息),服務(wù)器需要設(shè)置這個(gè)字段為 true。 |
Access-Control-Expose-Headers | 這個(gè)字段是可選的,它指定了響應(yīng)中可以被前端訪問(wèn)的其他頭部信息。 |
Content-Type | 表示響應(yīng)的文檔類型和字符編碼。 |
簡(jiǎn)單請(qǐng)求的處理相對(duì)較為簡(jiǎn)單,但需要服務(wù)器允許特定的跨域訪問(wèn)并設(shè)置相應(yīng)的 CORS 頭部來(lái)確保安全。
非簡(jiǎn)單請(qǐng)求
非簡(jiǎn)單 CORS 請(qǐng)求指的是不符合簡(jiǎn)單請(qǐng)求條件的跨域請(qǐng)求,如使用了 PUT 或 DELETE 方法,或者請(qǐng)求的 Content-Type 是 application/json 等。對(duì)于這樣的請(qǐng)求,瀏覽器會(huì)在正式發(fā)起請(qǐng)求之前先發(fā)送一個(gè) OPTIONS 類型的預(yù)檢請(qǐng)求。
預(yù)檢請(qǐng)求的目的是向服務(wù)器查詢是否允許來(lái)自網(wǎng)頁(yè)所在域名的請(qǐng)求,并了解可以使用哪些額外的頭信息字段。這個(gè)預(yù)檢請(qǐng)求(OPTIONS 請(qǐng)求)的頭部信息包括:
- Origin: 標(biāo)識(shí)請(qǐng)求來(lái)自哪個(gè)域,是必須的字段。
- Access-Control-Request-Method: 列出 CORS 請(qǐng)求會(huì)用到的 HTTP 方法,也是必須的字段。
- Access-Control-Request-Headers: 指定 CORS 請(qǐng)求會(huì)額外發(fā)送的頭信息字段,用逗號(hào)隔開(kāi)。
服務(wù)器收到這個(gè)預(yù)檢請(qǐng)求后,根據(jù)收到的信息判斷是否允許這個(gè)請(qǐng)求,如果允許,則返回相應(yīng)的 CORS 頭部信息。除了允許特定的跨域請(qǐng)求,服務(wù)器還可以在響應(yīng)頭部中添加 Access-Control-Max-Age 字段來(lái)緩存預(yù)檢請(qǐng)求的結(jié)果,減少后續(xù)請(qǐng)求的預(yù)檢次數(shù)。這個(gè)緩存只對(duì)完全一樣的 URL 生效,超出緩存時(shí)間后,再次發(fā)起相同的跨域請(qǐng)求仍會(huì)觸發(fā)預(yù)檢請(qǐng)求。
Nginx代理跨域
Nginx可以用作反向代理服務(wù)器,來(lái)解決跨域問(wèn)題。它可以代理客戶端的請(qǐng)求,并將請(qǐng)求發(fā)送到目標(biāo)服務(wù)器,再將目標(biāo)服務(wù)器的響應(yīng)返回給客戶端。這種方法類似于 CORS 跨域原理,但是它是通過(guò)服務(wù)器端進(jìn)行設(shè)置,而不是在瀏覽器端進(jìn)行設(shè)置。
以下是一個(gè)簡(jiǎn)單的 Nginx 配置示例,用于處理跨域請(qǐng)求:
server {
listen 81;
server_name www.domain1.com;
location / {
# 設(shè)置反向代理
proxy_pass http://xxxx1:8080;
# 修改 Cookie 中的域名
proxy_cookie_domain www.xxxx1.com www.xxxx2.com;
# 添加頭部信息以處理跨域請(qǐng)求
add_header Access-Control-Allow-Origin http://www.xxxx2.com; # 當(dāng)前端只跨域不帶 Cookie 時(shí),可以使用 *
add_header Access-Control-Allow-Credentials true;
}
}
這段配置的作用如下:
proxy_pass 指令用于指定反向代理的目標(biāo)服務(wù)器地址。proxy_cookie_domain 用于修改代理服務(wù)器返回的響應(yīng)中的 Cookie 中的域名,將它從源域名修改為目標(biāo)域名,確保 Cookie 在跨域時(shí)仍然有效。add_header 指令用于添加響應(yīng)頭部信息,其中 Access-Control-Allow-Origin 允許特定來(lái)源的跨域請(qǐng)求,Access-Control-Allow-Credentials 表示是否允許請(qǐng)求攜帶身份憑證(例如 Cookie)。
這種方法通過(guò) Nginx 作為代理服務(wù)器,處理了跨域請(qǐng)求的響應(yīng)頭部,允許指定的域名進(jìn)行跨域請(qǐng)求。這樣就可以在不修改前端代碼的情況下,實(shí)現(xiàn)跨域請(qǐng)求的需求。
Node中間件代理跨域
在?vue.config.js
?文件中,可以通過(guò)配置?devServer
?的?proxy
?選項(xiàng)實(shí)現(xiàn)代理轉(zhuǎn)發(fā):
module.exports = {
// 其他配置...
devServer: {
proxy: {
[process.env.VUE_APP_BASE_API]: {
target: 'http://xxxx', // 代理跨域目標(biāo)接口
ws: true,
changeOrigin: true,
pathRewrite: {
['^' + process.env.VUE_APP_BASE_API]: ''
}
}
}
}
}
-
proxy 字段用于配置代理。process.env.VUE_APP_BASE_API 是 Vue 項(xiàng)目中定義的環(huán)境變量,表示需要被代理的請(qǐng)求路徑前綴。
-
target 指定了代理的目標(biāo)地址,即請(qǐng)求將會(huì)被代理到這個(gè)地址下。
-
ws 表示是否代理 WebSocket。
-
changeOrigin 設(shè)置為 true 后,可以突破瀏覽器的同源策略,允許跨域。
-
pathRewrite 允許對(duì)請(qǐng)求路徑進(jìn)行重寫,將匹配到的路徑前綴去掉。比如,如果請(qǐng)求路徑是 /api/user,經(jīng)過(guò) pathRewrite 后就會(huì)變成 /user,將前綴 /api 去掉了。
當(dāng)使用 Node 中間件進(jìn)行代理跨域時(shí),你可以使用 http-proxy-middleware 包來(lái)創(chuàng)建一個(gè)代理服務(wù)器,讓后端服務(wù)(如 Express)處理跨域請(qǐng)求。這個(gè)中間件可以在 Express 應(yīng)用程序中使用,允許你在服務(wù)器端修改請(qǐng)求和響應(yīng),以便處理跨域問(wèn)題。
下面是一個(gè)在 Express 中使用 http-proxy-middleware 中間件的簡(jiǎn)單示例:
const express = require('express');
const { createProxyMiddleware } = require('http-proxy-middleware');
const app = express();
app.use('/', createProxyMiddleware({
// 代理跨域目標(biāo)接口
target: 'http://xxxx:8080',
changeOrigin: true,
// 修改響應(yīng)頭信息,實(shí)現(xiàn)跨域并允許帶cookie
onProxyRes: function(proxyRes, req, res) {
res.header('Access-Control-Allow-Origin', 'http://xxxx');
res.header('Access-Control-Allow-Credentials', 'true');
},
// 修改響應(yīng)信息中的 cookie 域名
cookieDomainRewrite: 'www.domain1.com' // 可以為 false,表示不修改
}));
app.listen(3000);
這段代碼做了以下事情:
-
引入了 Express 框架和 http-proxy-middleware。
-
創(chuàng)建了一個(gè) Express 應(yīng)用。
-
使用 app.use 將 createProxyMiddleware 中間件應(yīng)用到根路徑 /。
-
配置了 createProxyMiddleware,指定了目標(biāo)服務(wù)器的地址 target,開(kāi)啟了 changeOrigin 選項(xiàng)以確保源頭地址被更改為目標(biāo)地址。
-
在 onProxyRes 中修改了響應(yīng)頭部信息,允許跨域并設(shè)置了允許攜帶憑證(如 Cookie)。
-
cookieDomainRewrite 可以用于修改響應(yīng)信息中的 Cookie 域名,使其在傳輸中適應(yīng)跨域情況。
這種方式可以在后端服務(wù)器層面對(duì)跨域進(jìn)行處理,允許前端應(yīng)用向不同域名的后端服務(wù)發(fā)出請(qǐng)求。
WebSocket
WebSocket是一種在單個(gè) TCP 連接上進(jìn)行全雙工通信的協(xié)議,它允許客戶端和服務(wù)器之間進(jìn)行實(shí)時(shí)數(shù)據(jù)交換。與傳統(tǒng)的 HTTP 請(qǐng)求不同,WebSocket 的連接是持久性的,雙方可以隨時(shí)發(fā)送數(shù)據(jù)而不需要等待請(qǐng)求。
在跨域方面,WebSocket協(xié)議與傳統(tǒng)的 HTTP 請(qǐng)求不同,它不受同源策略的限制??梢允褂?ws://(非加密)和 wss://(加密)作為協(xié)議前綴,不受同源策略的約束,只要服務(wù)器支持 WebSocket,即可與客戶端進(jìn)行通信。
WebSocket請(qǐng)求頭中包含 Origin 字段,用于指示請(qǐng)求的來(lái)源域。服務(wù)器可以檢查這個(gè)字段來(lái)判斷是否允許與特定域的客戶端建立 WebSocket 連接。如果客戶端的來(lái)源域在服務(wù)器的白名單內(nèi),服務(wù)器將允許該連接的建立,否則可能會(huì)拒絕連接或執(zhí)行其他安全措施。
通過(guò) WebSocket,服務(wù)器和客戶端之間可以進(jìn)行持久的雙向通信,這種通信方式適用于實(shí)時(shí)性要求較高的場(chǎng)景,如在線聊天、實(shí)時(shí)數(shù)據(jù)傳輸?shù)取S捎诓皇芡床呗缘南拗疲琖ebSocket提供了一種跨域通信的可選方案。
下面是一個(gè)簡(jiǎn)單的例子,展示了如何使用 WebSocket 進(jìn)行跨域通信。
首先,假設(shè)有兩個(gè)域名分別是 domain1.com 和 domain2.com,我們將在 domain1.com 的頁(yè)面上創(chuàng)建 WebSocket 連接到 domain2.com 的服務(wù)器:
在 domain2.com 的服務(wù)器端,你需要有一個(gè) WebSocket 服務(wù)器,例如基于 Node.js 的 ws 模塊,用于監(jiān)聽(tīng) WebSocket 連接:
const WebSocket = require('ws');
const wss = new WebSocket.Server({ port: 8080 });
wss.on('connection', function connection(ws) {
ws.on('message', function incoming(message) {
console.log('Received: %s', message);
// 可以回復(fù)客戶端消息
ws.send('Hello, client!');
});
});
在?domain1.com
?的頁(yè)面上,你可以使用 JavaScript 來(lái)創(chuàng)建 WebSocket 連接到?domain2.com
?的服務(wù)器:
const socket = new WebSocket('ws://domain2.com:8080'); // WebSocket服務(wù)器的地址
socket.onopen = function(event) {
console.log('WebSocket連接已打開(kāi)');
socket.send('Hello, server!');
};
socket.onmessage = function(event) {
console.log('收到服務(wù)器消息:', event.data);
};
socket.onclose = function(event) {
if (event.wasClean) {
console.log('連接已關(guān)閉');
} else {
console.log('連接斷開(kāi)');
}
};
socket.onerror = function(error) {
console.error('WebSocket連接錯(cuò)誤:', error);
};
在這個(gè)例子中,domain1.com 的頁(yè)面通過(guò) WebSocket 連接到了 domain2.com 的服務(wù)器,并向其發(fā)送了消息。服務(wù)器收到消息后可以進(jìn)行處理,并且也可以通過(guò) WebSocket 向客戶端發(fā)送消息。
需要注意的是,WebSocket 協(xié)議在設(shè)計(jì)上允許跨域通信,因此不會(huì)受到瀏覽器同源策略的限制。但是,服務(wù)器端仍然可以根據(jù)自己的邏輯來(lái)判斷是否接受來(lái)自特定來(lái)源的連接。
postMessage
postMessage
?是 HTML5 中的一項(xiàng) API,它允許在不同窗口(包括 iframe)或不同來(lái)源的文檔間進(jìn)行安全地消息傳遞。這種通信機(jī)制可以用于多種場(chǎng)景:
1?? 頁(yè)面和新打開(kāi)的窗口之間的數(shù)據(jù)傳遞
2?? 不同窗口(包括不同域的窗口)之間的通信
3?? 頁(yè)面與嵌套的 iframe 之間的數(shù)據(jù)傳遞
4?? 不同源的跨域傳遞數(shù)據(jù)
postMessage 接受兩個(gè)參數(shù):
第一個(gè)參數(shù)是要發(fā)送的數(shù)據(jù),可以是字符串、對(duì)象等。
第二個(gè)參數(shù)是指定消息發(fā)送的目標(biāo)窗口的來(lái)源。這個(gè)參數(shù)通常是一個(gè)目標(biāo)窗口的 origin(協(xié)議 + 域名 + 端口),也可以是通配符 *(表示任意窗口),或者 /(表示與當(dāng)前窗口同源的窗口)。
例如,在一個(gè)頁(yè)面中,可以使用以下方式向另一個(gè)窗口發(fā)送消息:
// 獲取目標(biāo)窗口對(duì)象
const targetWindow = window.open('https://example.com', '_blank');
// 向目標(biāo)窗口發(fā)送消息
targetWindow.postMessage({ message: 'Hello, window!', value: 42 }, 'https://example.com');
在目標(biāo)窗口中,可以監(jiān)聽(tīng)?message
?事件來(lái)接收來(lái)自其他窗口的消息:
// 監(jiān)聽(tīng) message 事件
window.addEventListener('message', function(event) {
// 判斷消息來(lái)源是否符合預(yù)期
if (event.origin === 'https://sending-origin.com') {
// 處理接收到的消息
console.log('Received message:', event.data);
}
});
JSONP
JSONP(JSON with Padding)是一種利用 <script> 標(biāo)簽實(shí)現(xiàn)的跨域數(shù)據(jù)請(qǐng)求方法。其原理是通過(guò)動(dòng)態(tài)創(chuàng)建 <script> 標(biāo)簽,向服務(wù)器請(qǐng)求數(shù)據(jù),并在請(qǐng)求的 URL 中包含一個(gè)回調(diào)函數(shù)名。服務(wù)器收到請(qǐng)求后,將數(shù)據(jù)包裹在回調(diào)函數(shù)中返回給客戶端,從而繞過(guò)瀏覽器的同源策略限制。
JSONP 主要用于 GET 請(qǐng)求,并不適用于其他 HTTP 方法,且存在安全隱患,容易受到 XSS(跨站腳本攻擊)的影響。但它有一些優(yōu)點(diǎn),比如可以向不支持 CORS 的舊瀏覽器或不支持跨域請(qǐng)求的網(wǎng)站請(qǐng)求數(shù)據(jù)。
使用 JSONP 的示例代碼如下:
// 創(chuàng)建一個(gè)包含回調(diào)函數(shù)的 URL
const url = 'http://juejin.com/xxx?callback=handleCallback';
// 創(chuàng)建一個(gè) script 標(biāo)簽
const script = document.createElement('script');
// 設(shè)置 script 的 URL
script.src = url;
// 將 script 添加到頁(yè)面中
document.body.appendChild(script);
// 定義回調(diào)函數(shù),處理從服務(wù)器返回的數(shù)據(jù)
function handleCallback(res) {
console.log(res);
}
服務(wù)器接收到這個(gè)請(qǐng)求后,會(huì)將數(shù)據(jù)放在?handleCallback
?函數(shù)中返回,例如:
handleCallback({ code: 200, msg: 'success', data: [] });
在客戶端,這個(gè)函數(shù)?handleCallback
?將立即執(zhí)行,從而完成數(shù)據(jù)的處理和操作。
雖然 JSONP 具有一定的局限性和安全風(fēng)險(xiǎn),但在某些場(chǎng)景下仍然是一種有效的跨域數(shù)據(jù)獲取方式。
其他
除了以上提到的一些常見(jiàn)的解決跨域的方法以外,還有其他的方式可以來(lái)解決這個(gè)問(wèn)題。
1. document.domain + iframe:適用于主域名相同但子域名不同的跨域場(chǎng)景。當(dāng)兩個(gè)頁(yè)面的 document.domain 設(shè)置為同一個(gè)值(主域名),它們就可以相互通信。但這種方法僅適用于主域名相同的情況。
2. window.name + iframe:利用 iframe 的 window.name 屬性,這個(gè)屬性在不同頁(yè)面或者不同域名加載后依然保持不變。通過(guò)在不同頁(yè)面的 iframe 中設(shè)置和讀取 window.name,可以實(shí)現(xiàn)跨域通信。window.name 具有持久性,且可以存儲(chǔ)較大量的數(shù)據(jù)。
3. location.hash + iframe:適用于頁(yè)面間利用 URL 的 hash 部分來(lái)傳遞信息,特別是在 C 頁(yè)面幫助 A 頁(yè)面和 B 頁(yè)面進(jìn)行通信。通過(guò)改變 URL 的 hash 部分來(lái)傳遞信息,在不同頁(yè)面之間進(jìn)行簡(jiǎn)單的數(shù)據(jù)交換。
這些方法雖然可以解決一些特定的跨域通信問(wèn)題,但由于它們的特性和限制,通常只適用于特定場(chǎng)景,并且可能存在一些安全性或者容量方面的限制。因此,在使用這些方法時(shí),需要仔細(xì)考慮其適用范圍和可能帶來(lái)的安全隱患。文章來(lái)源:http://www.zghlxwxcb.cn/news/detail-810805.html
好啦,本文就到這里結(jié)束了,感謝閱讀~~文章來(lái)源地址http://www.zghlxwxcb.cn/news/detail-810805.html
到了這里,關(guān)于拓展邊界:前端世界的跨域挑戰(zhàn)的文章就介紹完了。如果您還想了解更多內(nèi)容,請(qǐng)?jiān)谟疑辖撬阉鱐OY模板網(wǎng)以前的文章或繼續(xù)瀏覽下面的相關(guān)文章,希望大家以后多多支持TOY模板網(wǎng)!