同源策略
限制从一个源加载的文档或者脚本与来自另一个源的资源进行交互。同源策略是一种用于隔离恶意文件的安全机制。
所谓的同源,指的是协议,域名,端口相同。
跨域通信的几种方式:
- JSONP
- WebSocket
- CORS
- Hash
- PostMessage
- document.domain
- window.name
- http-proxy
- nginx
JSONP
原理
通过script
标签异步加载实现。如使用script标签引入外部文件。
JSONP只支持GET请求。
实现
例一
<script src="http://www.test.com/?data=data&callback=myCallback"/>
例二
<script>
var util = {}
// 定义方法,动态创建script标签
util.createScript = function(url,charset) {
var script = document.createElement('script');
script.setAttribute('type','text/javaScript');
//定义外部脚本文件中所使用的字符编码:
charset && script.setAttribute('charset ', charset);
script.setAttribute('src', url);
script.async = true;
return script;
}
util.jsonp = function(url, onsuccess, onerror, charset) {
}
</script>
WebSocket
// 新建 WebSocket 实例。
var ws = new WebSocket("wss://echo.websocket.org");
// webSocket.readyState返回实例对象的当前状态,共有四种。
// CONNECTING:值为0,表示正在连接。
// OPEN:值为1,表示连接成功,可以通信了。
// CLOSING:值为2,表示连接正在关闭。
// CLOSED:值为3,表示连接已经关闭,或者打开连接失败。
switch (ws.readyState) {
case WebSocket.CONNECTING:
// do something
break;
case WebSocket.OPEN:
// do something
break;
case WebSocket.CLOSING:
// do something
break;
case WebSocket.CLOSED:
// do something
break;
default:
// this never happens
break;
}
// 把请求发出去
ws.onopen = function(evt) {
console.log("Connection open ...");
ws.send("Hello WebSockets!");
};
// 接收对方过来的消息
ws.onmessage = function(evt) {
console.log( "Received Message: " + evt.data);
ws.close();
};
// 关闭连接
ws.onclose = function(evt) {
console.log("Connection closed.");
};
http://www.ruanyifeng.com/blog/2017/05/websocket.html
CORS
跨域资源共享(CORS) 是一种机制,它使用额外的 HTTP 头来告诉浏览器 让运行在一个 origin (domain) 上的Web应用被准许访问来自不同源服务器上的指定的资源。
fetch是一个新的API,用来实现CORS通信。
fetch('/some/url',{
method: 'get',
}).then(function(res){
// code
}).catch(function(err){
// code
})
http://www.ruanyifeng.com/blog/2016/04/cors.html
Hash
url # 后面的内容就叫hash。Hash的改变页面不会刷新,这就是Hash做跨域的基本原理。
url ? 后面的内容叫Search,Search的改变会导致页面刷新。
// 例: 页面A通过iframe或frame嵌入了跨域页面B,A给B发消息。
// A页面
var B = document.getElementByTagName('iframe');
B.src = B.src + '#' + 'jsonString';
// B页面
// 通过onhashchange方法监听,url中hash是否发生变化。
window.onhashchange = function(){
var data = window.location.hash;
}
PostMessage
H5 新增postMessage方法可以用作跨域通信。
// 窗口A(http:A.com)向跨域窗口B(http:B.com)发送信息
// A窗口
// A 向B发信息,强调的是B窗口里的window对象。
window.postMessage('data','http:B.com')
// B 窗口
window.addEventListener("message", function(event){
// 获取url
console.log(event.origin)
// 获取A window对象
console.log(event.source)
// 获取传过来的数据
console.log(event.data)
});
备注:
旧版本XMLHttpRequest不支持跨域,也就是传统AJAX不支持跨域;新版本的XMLHttpRequest对象,可以向不同域名的服务器发出HTTP请求。这叫做"跨域资源共享"(Cross-origin resource sharing,简称CORS)。
http://www.ruanyifeng.com/blog/2012/09/xmlhttprequest_level_2.html