同源策略
同一协议、同一域名、同一端口
以上有一项不满足,浏览器就会出现 No ‘Access-Control-Allow-Origin’ header is present on the requested resource
为什么浏览器不支持跨域
cookie localStorage
Dom元素也有同源策略 iframe
ajax也不支持跨域
http是无状态,区分不了是谁发送的请求,因此网站给你发个cookie做个标志,如果么有同源策略,则可能会向恶意的网站发送请求,拿到你的密码等重要信息。。。。
实现跨域
jsonp
//后端部分
const http = require('http');
const express = require('express')
let app = express()
app.get('/say', function (req, res) {
let { wd, cb } = req.query
console.log(wd)
res.end(`${cb}('好的')`)
})
app.listen(9000)
// 客户端部分
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8" />
<meta http-equiv="X-UA-Compatible" content="IE=edge" />
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
<title>Document</title>
</head>
<body></body>
<script>
// 2 后端 callbackName(数据)
function onResponse(posts) {
console.log(posts);
}
function show(data) {
console.log("执行show", data);
}
function jsonp({ url, params, cb }) {
return new Promise((resovle, reject) => {
window[cb] = function (data) {
resovle(data);
document.body.removeChild(script);
};
let arrs = [];
let script = document.createElement("script");
params = { ...params, cb };
console.log(params);
for (const key in params) {
arrs.push(`${key}=${params[key]}`);
}
console.log(params);
script.src = `${url}?${arrs.join("&")}`;
document.body.appendChild(script);
});
}
jsonp({
url: "http://localhost:9000/say",
params: { wd: "我爱中国" },
cb: "show",
}).then((data) => {
console.log(data);
});
</script>
<!-- <script src="http://localhost:9090/api"></script> -->
</html>
jsonp的执行流程其实就是简单的两步。
- 第一,在前端预先定义好一个带参数的回调函数用来接收后端传来的数据。
- 第二,在后端启动一个server服务,将要传的数据以定义好了的回调函数名加上返回结果的方式传给前端
- 优点
- 它不像XMLHttpRequest对象实现的Ajax请求那样受到同源策略的限制
- 它的兼容性更好,在更加古老的浏览器中都可以运行,不需要XMLHttpRequest或ActiveX的支持
- 并且在请求完毕后可以通过调用callback的方式回传结果
- 缺点
const express = require(‘express’) let app = express() app.use(express.static(__dirname)) // localhost:9000 跑index.html文件 app.listen(9000)
// server2.js const express = require(‘express’) let app = express() app.get(‘/getData’, function (req, res) { res.end(‘我是另一个域的数据哈哈哈哈’) }) app.listen(9090)
客户端部分index.html
```javascript
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8" />
<meta http-equiv="X-UA-Compatible" content="IE=edge" />
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
<title>Document</title>
</head>
<body>
liang
</body>
<script>
let xhr = new XMLHttpRequest();
xhr.open("GET", "http://localhost:9090/getData", true);
xhr.onreadystatechange = function () {
if ((xhr.status >= 200 && xhr.status < 300) || xhr.status === 304) {
console.log(xhr.response);
}
};
xhr.send();
</script>
</html>
// 数据是可以发送到服务器,只是服务器返回的结果被浏览器屏蔽了
访问http://localhost:9000/
解决 :设置请求源
const express = require('express')
let app = express()
let whiteList = ['http://localhost:9000'] // 可以访问源,白名单
app.use(function (req, res, next) {
let origin = req.headers.origin
if (whiteList.includes(origin)) {
res.setHeader('Access-Control-Allow-Origin', origin)//* 代表接受任何源
}
next()
})
app.get('/getData', function (req, res) {
res.end('我是另一个域的数据哈哈哈哈')
})
app.listen(9090)
postMessage
a页面中嵌入b页面,并给b页面发送数据‘hello 我是a’;
b页面收到a发来的数据;给a回复
// a.html
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8" />
<meta http-equiv="X-UA-Compatible" content="IE=edge" />
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
<title>Document</title>
</head>
<body>
<iframe
src="http://localhost:4000/b.html"
frameborder="0"
id="frame"
onload="load()"
></iframe>
</body>
<script>
function load() {
let frame = document.getElementById("frame");
// 发送hello 我是a给b页面
frame.contentWindow.postMessage("hello 我是a", "http://localhost:4000");
window.onmessage = function (e) {
console.log(e.data);
};
}
</script>
</html>
// b.html
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8" />
<meta http-equiv="X-UA-Compatible" content="IE=edge" />
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
<title>Document</title>
</head>
<body>
b
</body>
<script>
window.onmessage = function (e) {
console.log("b接收到的", e.data);
e.source.postMessage("我给a答复:你好,我是b", e.origin);
};
</script>
</html>
// a.js
//后端部分
const express = require('express')
let app = express()
app.use(express.static(__dirname)) // localhost:9000 跑index.html文件
app.listen(3000)
// b.js
//后端部分
const express = require('express')
let app = express()
app.use(express.static(__dirname)) // localhost:9000 跑index.html文件
app.listen(4000)
访问http://localhost:3000/a.html
document.domain
window.name
拿到跳转页面的window.name的值
c.html
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8" />
<meta http-equiv="X-UA-Compatible" content="IE=edge" />
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
<title>Document</title>
</head>
<body>
我是C
</body>
<script>
window.name = "我的name是liangchunjian";
</script>
</html>
a.html
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8" />
<meta http-equiv="X-UA-Compatible" content="IE=edge" />
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
<title>Document</title>
</head>
<body>
<iframe
src="http://localhost:4000/c.html"
frameborder="0"
id="frame"
onload="load()"
></iframe>
</body>
<script>
// a,b同域
// c独立
// a获取c的数据
// a先引用c,c把数据放在window.name
let first = true;
function load() {
let frame = document.getElementById("frame");
if (first) {
frame.src = "http://localhost:3000/b.html";// 切换到b
first = false;
} else {
console.log(frame.contentWindow.name); // 拿到通过name拿到c中的数据
}
}
</script>
</html>