1.什么是跨域
当一个请求url的协议、域名、端口三者之间任意一个与当前的url不一样即为跨域
ex:
http//www.... 和https//www....就是协议上的跨域(http/https)
www.baidu.com 和www.test.com 就是主域名不一样(baidu/test)
www.test.com 和blog.test.com 就是子域名不一样(WWW/blog)
www.test.com:8080 和www.test.com:7000 端口上的跨域(8080/7000)
2.为何浏览器会禁止跨域
由于跨域的访问会带来许多安全性上的问题,cookie通常都用于状态控制,存储登陆的信息,若是容许跨域,那么别的网站用一段脚本就能够轻松获取你的cookie数据,而且冒充身份去登陆网站(这不一下就被盗号了吗),存在极大的安全隐患,因此,如今的浏览器都采用同源策略
3.非同源限制
1.没法读取非同源网页的Cookie、Localstorage和indexedDB
2.没法接触非同源网页的DOM节点
3.没法向非同源地址发送ajax请求
注:有三个标签容许跨域加载资源
1.<img src='xxx'>
2.<link href='xxx'>
3.<script src='xxx'>
4.如何解决跨域访问问题
1.document.domain
两个页面能够经过设置相同的document.domain,由于浏览器是经过document.domain属性来检查两个网页是否同源
使用:两个网页都设置document.domain='test.com' #不是固定的,本身想名字噢
缺点:这方式的局限性比较大,由于只能用于二级域名相同的状况下,好比说,a.test.com 和 b.test.com 适用该方式
2.JSONP
利用<script>元素的开放策略,向服务器请求 JSON 数据,服务器收到请求后,将数据放在一个指定名字的回调函数的参数位置传回来。
与ajax的区别:
JSONP和ajax相同,都是客户端向服务器端发送请求,从服务器端获取数据的方式。但ajax属于同源策略,JSONP属于非同源策略(跨域请求)
优势:兼容性好
缺点:只支持get,不支持post
使用:
1.声明一个回调函数,其函数名(如fn)当作参数值,要传递给跨域请求数据的服务器,函数形参为要获取目标数据(服务器返回的data)。
2.建立一个<script>标签,把那个跨域的API数据接口地址,赋值给script的src,还要在这个地址中向服务器传递该函数名(能够经过问号传参:?callback=fn)。
3.服务器接收到请求后,须要进行特殊的处理:把传递进来的函数名和它须要给你的数据拼接成一个字符串,例如:传递进去的函数名是fn,它准备好的数据是fn([{"name":"jianshu"}])。
4.最后服务器把准备的数据经过HTTP协议返回给客户端,客户端再调用执行以前声明的回调函数(fn),对返回的数据进行操做。
<script type="text/javascript"src="http://crossdomain.com/jsonServerResponse?jsonp=fn"> </script>
<script type="text/javascript">
function fn(data){
//处理得到的数据
}
</script>
其中 fn 是客户端注册的回调的函数,目的获取跨域服务器上的json数据后,对数据进行在处理。
最后服务器返回给客户端数据的格式为:
fn({ msg:'this is json data'})
3.CORS
CORS 是跨域资源分享(Cross-Origin Resource Sharing)的缩写。它是 W3C 标准,属于跨源 AJAX 请求的根本解决方法。整个CORS通讯过程都是浏览器自动完成的,不须要用户参与,浏览器一旦发现AJAX请求跨源,会自动添加一些附加的头信息,有时还会多出一次附加的请求,用户不会有感受,所以,实现CORS通讯的关键是服务器,只要服务器实现了CORS接口,就能够跨源通讯
优势:功能更增强大支持各类HTTP Method
缺点:兼容性不如JSONP
使用:
1.前端代码(须要判断浏览器是否支持状况)
function createCORSRequest(method, url) {var xhr = new XMLHttpRequest();
if ("withCredentials" in xhr) {
// 此时即支持CORS的状况
// 检查XMLHttpRequest对象是否有“withCredentials”属性
// “withCredentials”仅存在于XMLHTTPRequest2对象里
xhr.open(method, url, true);
} else if (typeof!= "undefined") {
// 不然检查是否支持XDomainRequest,IE8和IE9支持
// XDomainRequest仅存在于IE中,是IE用于支持CORS请求的方式
xhr = new XDomainRequest();
xhr.open(method, url);
} else {
// 不然,浏览器不支持CORS
xhr = null;
}
return xhr;
}
var xhr = createCORSRequest('GET', url);
if (!xhr) {
throw new Error('CORS not supported');
}
服务器:
Apache须要使用mod_headers模块来激活HTTP头的设置,它默认是激活的。你只须要在Apache配置文件的<Directory>, <Location>, <Files>或<VirtualHost>的配置里加入如下内容便可
Header set Access-Control-Allow-Origin *
4.跨文档通讯 API:window.postMessage()
调用postMessage方法实现父窗口http://test1.com向子窗口http://test2.com发消息(子窗口一样能够经过该方法发送消息给父窗口)
// 父窗口打开一个子窗口
var openWindow = window.open('http://test2.com', 'title');
// 父窗口向子窗口发消息(第一个参数表明发送的内容,第二个参数表明接收消息窗口的url)
openWindow.postMessage('Nice to meet you!', 'http://test2.com');
// 监听 message 消息
window.addEventListener('message', function (e) {
console.log(e.source); // e.source 发送消息的窗口
console.log(e.origin); // e.origin 消息发向的网址
console.log(e.data); // e.data 发送的消息
},false);
5.WebSocket
Websocket是HTML5的一个持久化的协议,它实现了浏览器与服务器的全双工通讯,同时也是跨域的一种解决方案。WebSocket和HTTP都是应用层协议,都基于 TCP 协议。可是 WebSocket 是一种双向通讯协议,在创建链接以后,WebSocket 的 server 与 client 都能主动向对方发送或接收数据。同时,WebSocket 在创建链接时须要借助 HTTP 协议,链接创建好了以后 client 与 server 之间的双向通讯就与 HTTP 无关了。
原生WebSocket API使用起来不太方便,咱们使用Socket.io,它很好地封装了webSocket接口,提供了更简单、灵活的接口,也对不支持webSocket的浏览器提供了向下兼容。
1.前端代码
<div>user input:<input type="text"></div>
<script src="./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>
2.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.');
});
});