浏览器的安全策略
,不是HTTP协议的一部分。所以 服务器端 调用HTTP接口只是使用HTTP协议,不会执行JS脚本,不需要同源策略,也就不存在跨越问题。协议+域名+端口号
三者相同,只要有一个不一样,就会发生跨域script
、img
、link
、iframe
标签不存在跨域请求限制script标签
去调用跨域的接口,把 参数
和 回调函数名
(需要是全局函数)传给服务器,服务器接收客户端请求,给客户端返回 回调函数 和 数据的字符串,浏览器拿到字符串进行解析,然后执行函数。GET请求
、需要服务端支持、安全性不好// 处理成功失败返回格式的工具
const {successBody} = require(‘../utli‘)
class CrossDomain {
static async jsonp (ctx) {
// 前端传过来的参数
const query = ctx.request.query
// 设置一个cookies
ctx.cookies.set(‘tokenId‘, ‘1‘)
// query.cb是前后端约定的方法名字,其实就是后端返回一个直接执行的方法给前端
// 由于前端是用script标签发起的请求,所以返回了这个方法后相当于立马执行,并且把要返回的数据放在方法的参数里。
ctx.body = `${query.cb}(${JSON.stringify(successBody({msg: query.msg}, ‘success‘))})`
}
// 因为返回的数据是字符串,所以这里要写stringify使浏览器解析完后能执行把数据转成json格式
}
module.exports = CrossDomain
简单版前端:
// 后端返回直接执行的方法,相当于执行这个方法,由于后端把返回的数据放在方法的参数里,所以这里能拿到res。
window.jsonpCb = function (res) { console.log(res) }
<script src=‘http://localhost:9871/api/jsonp?msg=helloJsonp&cb=jsonpCb‘></script>
cookie
请求:前后端都需要设置。xhr.withCredentials = true; // 前端设置是否带cookie
OPTIONS
(试探性)请求,看是否可以和服务器建立跨域传输,再传真正的请求。代理服务器
,实现 数据的转发,也可以通过设置 cookieDomainRewrite
参数修改响应头中cookie中域名,实现当前域的cookie写入,方便接口登录认证。webpack
和 webpack-dev-server
这个暂时还未去学习,先空着吧,大概就是有这么个东西
postMessage
是HTML5 XMLHttpRequest Level 2中的API,且是为数不多 可以跨域操作的windowd属性* 之一,它可用于解决以下方面的跨域数据传递:
postMessage(data,origin)
方法接受 两个参数
data
:html5规范支持任意基本类型或可复制的对象,但部分浏览器只支持字符串,所以传参时最好用 JSON.stringify()
序列化。(另一方在用JSON.parse()
转回来)origin
:协议+主机+端口号,也可以设置为"*",表示可以传递给任意窗口,如果要指定和当前窗口同源的话设置为"/"。<iframe id="iframe" src="http://www.domain2.com/b.html" style="display:none;">
</iframe>
<script>
var iframe = document.getElementById(‘iframe‘);
iframe.onload = function() {
var data = {
name: ‘aym‘
};
// 向domain2传送跨域数据
iframe.contentWindow.postMessage(JSON.stringify(data), ‘http://www.domain2.com‘);
};
// 接受domain2返回数据
window.addEventListener(‘message‘, function(e) {
alert(‘data from domain2 ---> ‘ + e.data);
}, false);
</script>
b.html:(http://www.domain2.com/b.html)
<script>
// 接收domain1的数据
window.addEventListener(‘message‘, function(e) {
alert(‘data from domain1 ---> ‘ + e.data);
var data = JSON.parse(e.data);
if (data) {
data.number = 16;
// 处理后再发回domain1
window.parent.postMessage(JSON.stringify(data), ‘http://www.domain1.com‘);
}
}, false);
</script>
WebSocket protocol
是HTML5一种新的协议。它实现了 浏览器与服务器全双工通信,同时 允许跨域通讯,是 server push
技术的一种很好的实现。<div>user input:<input type="text"></div>
<script src="https://cdn.bootcss.com/socket.io/2.2.0/socket.io.js"></script>
<script>
var socket = io(‘http://www.domain2.com:8080‘);
// 连接成功处理
socket.on(‘connect‘, function() {
// 监听服务端消息
socket.on(‘message‘, function(msg) {
console.log(‘data from server: ---> ‘ + msg);
});
// 监听服务端关闭
socket.on(‘disconnect‘, function() {
console.log(‘Server socket has closed.‘);
});
});
document.getElementsByTagName(‘input‘)[0].onblur = function() {
socket.send(this.value);
};
</script>
Nodejs socket后台
var http = require(‘http‘);
var socket = require(‘socket.io‘);
// 启http服务
var server = http.createServer(function(req, res) {
res.writeHead(200, {
‘Content-type‘: ‘text/html‘
});
res.end();
});
server.listen(‘8080‘);
console.log(‘Server is running at port 8080...‘);
// 监听socket连接
socket.listen(server).on(‘connection‘, function(client) {
// 接收信息
client.on(‘message‘, function(msg) {
client.send(‘hello:‘ + msg); //给客户端发送信息
console.log(‘data from client: ---> ‘ + msg);
});
// 断开处理
client.on(‘disconnect‘, function() {
console.log(‘Client socket has closed.‘);
});
});
domain.com
,子域不同 www和child
的跨域应用场景document.domain
设置成 主域,就实现了同域。<iframe id="iframe" src="http://child.domain.com/b.html"></iframe>
<script>
document.domain = ‘domain.com‘;
var user = ‘admin‘;
</script>
子窗口 如:http://child.domain.com/b.html
<script>
document.domain = ‘domain.com‘;
// 获取父窗口中变量
alert(‘get js data from parent ---> ‘ + window.parent.user);
</script>
大小限制(4kb左右)
,不能传复杂数据。iframe
的 location.hash
传值,相同域之间直接js访问来通信。(PS:A和C同源,A和B不同源)hash值单向通信
,b与c也不同域也只能单向通信,但c与a同域,所以c可通过 parent.parent
访问a页面所有对象。<iframe id="iframe" src="http://www.domain2.com/b.html" style="display:none;">
</iframe>
<script>
var iframe = document.getElementById(‘iframe‘);
//1:向b.html传hash值
setTimeout(function() {
iframe.src = iframe.src + ‘#user=admin‘; //其中‘#user=admin‘是hash值
}, 1000);
// 开放给同域c.html的回调方法
function onCallback(res) {
alert(‘data from c.html ---> ‘ + res);
}
</script>
b.html:(http://www.domain2.com/b.html)
<iframe id="iframe" src="http://www.domain1.com/c.html" style="display:none;">
</iframe>
<script>
var iframe = document.getElementById(‘iframe‘);
//2:监听a.html传来了hash值‘#user=admin‘,hash值发生变化,再传给c.html
window.onhashchange = function () {
iframe.src = iframe.src + location.hash;
};
</script>
c.html:(http://www.domain1.com/c.html)
<script>
//3: 监听到b.html传来了hash值,hash变化了
window.onhashchange = function () {
// 再通过操作同域a.html的js回调,将结果传回
window.parent.parent.onCallback(location.hash.replace(‘#user=‘, ‘‘));
};
</script>
跨域是因为浏览器的安全考虑,那就直接去改浏览器的设置啦。
原文:https://www.cnblogs.com/baboon/p/13053139.html