九種 「姿勢」 讓你徹底解決跨域

let script = document.createElement("script"); document.body.removeChild(script); document.body.appendChild(script);script.src = "http://192.168.0.57:8080/xss.js";

會把別人的腳本引入到自己的頁面中執行,如:彈窗、廣告等,甚至更危險的腳本程序。

二、使用 CORS 跨域

跨源資源共享/CORS(Cross-Origin Resource Sharing)是 W3C 的一個工作草案,定義了在必須訪問跨源資源時,瀏覽器與服務器應該如何溝通。CORS 背後的基本思想,就是使用自定義的 HTTP 頭部讓瀏覽器與服務器進行溝通,從而決定請求或響應是應該成功,還是應該失敗。

使用場景:多用於開發時,前端與後臺在不同的 ip 地址下進行數據訪問。

現在啟動兩個端口號不同的服務器,創建跨域條件,服務器(NodeJS)代碼如下:

// 服務器1
const express = require(express);
let app = express();
app.use(express.static(__dirname));
app.listen(3000);
// 服務器2
const express = require("express");
let app = express();
app.get("/getDate", function(req, res) {
res.end("I love you");
});
app.use(express.static(__dirname));
app.listen(4000);

由於我們的 NodeJS 服務器使用 express 框架,在我們的項目根目錄下的命令行中輸入下面代碼進行安裝:

npm install express --save

通過訪問 http://localhost:3000/index.html 獲取 index.html 文件並執行其中的 Ajax 請求 http://localhost:4000/getDate 接口去獲取數據,index.html 文件內容如下:






CORS 跨域





上面 index.html 代碼中發送請求訪問不在同源的服務器 2,此時會在控制檯給出錯誤信息,告訴我們缺少了哪些響應頭,我們對應報錯信息去修改訪問的服務器 2 的代碼,添加對應的響應頭,實現 CORS 跨域。

// 服務器2
const express = require("express");
let app = express();
// 允許訪問域的白名單
let whiteList = ["http://localhost:3000"];
app.use(function(req, res, next) {
let origin = req.header.origin;
if (whiteList.includes(origin)) {
// 設置那個源可以訪問我,參數為 * 時,允許任何人訪問,但是不可以和 cookie 憑證的響應頭共同使用
res.setHeader("Access-Control-Allow-Origin", origin);
// 想要獲取 ajax 的頭信息,需設置響應頭
res.setHeader("Access-Control-Allow-Headers", "name");
// 處理複雜請求的頭
res.setHeader("Access-Control-Allow-Methods", "PUT");

// 允許發送 cookie 憑證的響應頭
res.setHeader("Access-Control-Allow-Credentials", true);
// 允許前端獲取哪個頭信息
res.setHeader("Access-Control-Expose-Headers", "name");
// 處理 OPTIONS 預檢的存活時間,單位 s
res.setHeader("Access-Control-Max-Age", 5);
// 發送 PUT 請求會做一個試探性的請求 OPTIONS,其實是請求了兩次,當接收的請求為 OPTIONS 時不做任何處理
if (req.method === "OPTIONS") {
res.end();
}
}
next();
});
app.put("/getDate", function(req, res) {
// res.setHeader('name', 'nihao'); // 設置自定義響應頭信息
res.end("I love you");
});
app.get("/getDate", function(req, res) {
res.end("I love you");
});
app.use(express.static(__dirname));
app.listen(4000);

三、使用 postMessage 實現跨域

postMessage 是 H5 的新 API,跨文檔消息傳送(cross-document messaging),有時候簡稱為 XMD,指的是在來自不同域的頁面間傳遞消息。

調用方式:window.postMessage(message, targetOrigin)

  • message:發送的數據
  • targetOrigin:發送的窗口的域

在對應的頁面中用 message 事件接收,事件對象中有 data、origin、source 三個重要信息

  • data:接收到的數據
  • origin:接收到數據源的域(數據來自哪個域)
  • source:接收到數據源的窗口對象(數據來自哪個窗口對象)

使用場景:不是使用 Ajax 的數據通信,更多是在兩個頁面之間的通信,在 A 頁面中引入 B 頁面,在 A、B 兩個頁面之間通信。

與上面 CORS 類似,我們要創建跨域場景,搭建兩個端口號不同的 Nodejs 服務器,後面相同方式就不多贅述了。

// 服務器1
const express = require(express);
let app = express();
app.use(express.static(__dirname));
app.listen(3000);
// 服務器2
const express = require(express);
let app = express();
app.use(express.static(__dirname));
app.listen(4000);

通過訪問 http://localhost:3000/a.html,在 a.html 中使用 iframe 標籤引入 http://localhost:4000/b.html,在兩個窗口間傳遞數據。

 





頁面 A