同源策略指 “协议 + 域名 + 端口” 三者相同,其中一者不同即是跨域
跨域限制以下几种行为:
1.cookie localstorage 和 indexDB 无法读取
2.dom和js对象无法获取
3.不能发送ajax请求
解决方案:
1.jsonp实现跨域
原生:
<script>
var script = document.createElement('script');
script.type = 'text/javascript';
script.src = 'http://www.xxx.com:8080/login?user=admin&callback=handleCallback';
document.head.appendChild(script);
function handleCallback(res) {
alert(JSON.stringify(res));
}
</script>
jquery ajax
$.ajax({
url: 'http://www.xxx.com:8080/login',
type: 'get',
dataType: 'jsonp', // 请求方式为jsonp
jsonpCallback: "handleCallback", // 自定义回调函数名
data: {}
});
vue.js
this.$http.jsonp('http://www.xxx.com:8080/login', {
params: {},
jsonp: 'handleCallback'
}).then((res) => {
console.log(res);
})
缺点:只能用于get请求
2.设置请求头
Access-Control-Allow-Origin: | *
Access-Control-Expose-Headers
让服务器把允许浏览器访问的头放入白名单
Access-Control-Max-Age
指定了preflight请求的结果能够被缓存多久
Access-Control-Allow-Credentials
指定了当浏览器的credentials设置为true时是否允许浏览器读取response的内容。
Access-Control-Allow-Methods
首部字段用于预检请求的响应。其指明了实际请求所允许使用的 HTTP 方法。
Access-Control-Allow-Headers
首部字段用于预检请求的响应。其指明了实际请求中允许携带的首部字段。
const http = require("http");
const sever = http.createServer();
sever.on("request",(req,res)=>{
res.setHeader("Access-Control-Allow-Origin","*");
res.setHeader("Access-Control-Allow-Methods","DELETE,PUT,GET,POST,OPTIONS")
if(req.url == "/getData" && req.method == "GET"){
const data = {};
res.end(JSON.stringify(data));
}
})
sever.listen(3000);
3.postMessage
h5新增
语法:
otherWindow.postMessage(message, targetOrigin, [transfer]);
otherWindow
其他窗口的一个引用,比如iframe的contentWindow属性、执行window.open返回的窗口对象、或者是命名过或数值索引的window.frames。
targetOrigin
通过窗口的origin属性来指定哪些窗口能接收到消息事件,其值可以是字符串"*"(表示无限制)或者一个URI。在发送消息的时候,如果目标窗口的协议、主机地址或端口这三者的任意一项不匹配targetOrigin提供的值,那么消息就不会被发送;只有三者完全匹配,消息才会被发送。这个机制用来控制消息可以发送到哪些窗口;例如,当用postMessage传送密码时,这个参数就显得尤为重要,必须保证它的值与这条包含密码的信息的预期接受者的origin属性完全一致,来防止密码被恶意的第三方截获。如果你明确的知道消息应该发送到哪个窗口,那么请始终提供一个有确切值的targetOrigin,而不是*。不提供确切的目标将导致数据泄露到任何对数据感兴趣的恶意站点。
transfer 可选
是一串和message 同时传递的 Transferable 对象. 这些对象的所有权将被转移给消息的接收方,而发送一方将不再保有所有权。
<script>
// 接收otherwindow的数据
window.addEventListener('message', function(e) {
alert('data from domain1 ---> ' + e.data);
var data = JSON.parse(e.data);
if (data) {
data.number = 16;
// 处理后再发回otherwindow
window.parent.postMessage(JSON.stringify(data), 'http://www.xxx.com');
}
}, false);
</script>