同源策略(Same origin Policy)
游览器处于安全方面考虑,只允许与本域下的接口交互。不同源的客户端在没有明确授权的情况下,不能读写对方资源
本域指的是
- 同协议: 如都是http或者https
- 同域名: 如都是http://gerkeytop/a和http://gerkeytop/b
- 同端口: 如都是80端口
只有这三个相同才能调用相同域下的接口(主要是看 执行js的文件处于什么位置)
跨域的几种方法
JSONP
HTML中的script标签可以加载其它域下面的js,比如我们经常引入一线上的个其它域cdn的jquery
DOME
//后端提供一个接口(不管部署在什么平台(node,java,php..))
//后端提供了一个调用天气的的接口
http://api.jirengu.com/weather.php
//index.html 所在位置是 http://gerkeytop.com/index.html
ajax("http://api.jirengu.com/weather.php") 这样直接掉就会报跨域不通过(因为是在不同的域下面)
//解决JSONP(利用script标签方式去请求接口) 传一个callback回调函数
<head>
<script src="http://api.jirengu.com/weather.php?callback=showData"></script>
</head>
<script>
function showData(data){
console.log(data); 获取到后端返回的数据
}
</script>
复制代码
callback回调原理(后端接口要配合):
前端: script加载资源 -> 返回字符串文本 -> 丢在当前环境中被立即执行 后端: 返回一个类似于:"callback(['json字符串'])"格式的数据 前端: 定义一个callback函数,用于接收数据 前端: 在script标签中配上调用地址和callback 当后端返回格式的字符串(带上数据)立即被执行callback函数,刚好之前有定义callback 执行拿到data
CORS(Cross-Origin Resource Sharing)
CORS全称是 跨域资源共享 方式很简单,当你使用 XMLHttpRequest 发送请求时,浏览器发现该请求不符合同源策略,会给该请求加一个请求头:Origin,后台进行一系列处理,如果确定接受请求则在返回结果中加入一个响应头:Access-Control-Allow-Origin; 浏览器判断该相应头中是否包含 Origin 的值,如果有则浏览器会处理响应,我们就可以拿到响应数据,如果不包含浏览器直接驳回,这时我们无法拿到响应数据。所以 CORS 的表象是让你觉得它与同源的 ajax 请求没啥区别,代码完全一样。
兼容性: Chrome 3+, Firefox 3.5+, IE 10+, Opera 12+, Safari 4+
IE8-IE9则需要使用window.XDomainRequest.来兼容
DOME
//后端提供了一个调用天气的的接口
http://api.jirengu.com/weather.php
//后端将这个接口在接口返回时设置
res.setHeader('Access-Control-Allow-Origin','http://api.jirengu.com')
或者
//res.setHeader('Access-Control-Allow-Origin','*')
复制代码
降域(接口调用无关,主要对于当前页面下iframe的操作)
iframe的同源策略问题 在当前页面下的iframe的域若与当前域名不同源,,则当前页面js对iframe无法操作
降域: 例如: 当前页域名是 http://a.gerkeytop.me 和 http://b.gerkeytop.me 后面的gerkeytop.me相同,那么就可以使用document.domain将二者的域名设置为gerkeytop.me 来实现同源
顶级域名无法降域(例如:无法修改a,b层的值) 当前页需要设置 document.domain ,iframe也需要设置document.domain 两者都设置才可以
DOME
//当前页
<div class="container">
<div class="main">
<input type="text">
</div>
<iframe src="http://b.justfun.me:8080/iframe.html" frameborder="0"></iframe>
</div>
<script>
var inputNode = document.querySelector('.container .main input')
inputNode.setAttribute('placeholder', '我是当前网页,我的域名是' + location.origin)
// console.log(window.frames[0].document.body) // 执行这行代码会报错,因为当前网页获取不到任何有关iframe的信息
document.domain = 'justfun.me'
// 注意:顶级域名无法进行降域
</script>
//iframe
<div class="container">
<div class="main">
<input type="text">
</div>
</div>
<script>
var inputNode = document.querySelector('.container .main input')
inputNode.setAttribute('placeholder', '我是iframe,我的域名是' + location.origin)
document.domain = 'justfun.me'
</script>
复制代码
postMessage(H5-API)
能做的事情:
- 页面和其打开的新窗口的数据传递
- 多窗口之间消息传递
- 页面与嵌套的iframe消息传递
- 上面三个问题的跨域数据传递
兼容性: IE10+, Firefox 3.1+, Opera 9+, Safari, and Chrome
概念及特点: postMessage()方法允许来自不同源的脚本采用异步方式进行有限的通信,可以实现跨文本档、多窗口、跨域消息传递
使用方法: postMessage(data,origin)
-
data:要传递的数据,html5规范中提到该参数可以是JavaScript的任意基本类型或可复制的对象,然而并不是所有浏览器都做到了这点儿,部分浏览器只能处理字符串参数,所以我们在传递参数的时候需要使用JSON.stringify()方法对对象参数序列化,在低版本IE中引用json2.js可以实现类似效果。
-
origin:字符串参数,指明目标窗口的源,协议+主机+端口号[+URL],URL会被忽略,所以可以不写,这个参数是为了安全考虑,postMessage()方法只会将message传递给指定窗口,当然如果愿意也可以建参数设置为"*",这样可以传递给任意窗口,如果要指定和当前窗口同源的话设置为"/"
DOME
// http://test.com/index.html通过postMessage()方法向跨域的iframe页面http://lsLib.com/lsLib.html传递消息
//http://test.com/index.html 界面下
window.frames[0].postMessage('getcolor','http://lslib.com');
//http://lslib.com/lslib.html 界面下
window.addEventListener('message',function(e){
if(e.source!=window.parent) return;
var color=container.style.backgroundColor;
window.parent.postMessage(color,'*');
},false);
复制代码
Web Worker js实现多线程(消息传递)
主要处理复杂数据异步计算
- Web Worker无法访问DOM节点
- Web Worker无法访问全局变量或是全局函数
- Web Worker无法调用alert()或者confirm之类的函数
- Web Worker无法访问window、document之类的浏览器全局变量
它允许在 Web 程序中并发执行多个 JavaScript 脚本,每个脚本执行流都称为一个线程,彼此间互相独立,并且有浏览器中的 JavaScript 引擎负责管理