九种 “姿势” 让你彻底解决跨域

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