协议、子域名、主域名、端口号中任意一个不相同时,都算作不同域。
跨域是指服务端能收到客户端请求并正常返回返回结果,结果被浏览器拦截。
PS:如果是协议和端口问题,“前台”无法解决
允许跨域加载资源的标签:
<img src="XXX">
<link href="XXX">
<script src="XXX">
JSONP
需要对方的服务器做支持,后台也返回json数据
优点:兼容性好。缺点:只支持get方法。
流程:
- 声明一个回调函数,函数名当做参数值,要传递给跨域请求数据的服务器,函数形参为要获取目标数据(服务器返回的data)
- 创建一个<script>标签,src为跨域API数据接口地址,通过“?”传参
<script type="text/javascript">
function fn(data) {
alert(data.msg);
}
</script>
<script type="text/javascript" src="http://crossdomain.com/jsonServerResponse?jsonp=fn"></script>
jquery的jsonp
$.ajax({
url:'http://crossdomain.com/jsonServerResponse',
dataType:'jsonp',
type:'get', //可以省略
jsonpCallback:'fn', //客户端传递给服务器的函数名,可省略
jsonp:'jsonp', //把客户端传递的函数参数callback变成jsonp,可省略
success:function(data){
console.log(data);
}
});
CORS
只要服务器实现了CORS接口,就可以实现跨域
要求:浏览器(>IE10)和服务器的同时支持,是跨越的根本解决办法,由浏览器自动完成
服务器端:
header('Access-Control-Allow-Origin:*');
header('Access-Control-Allow-Methods:POST,GET');
WebSocket
HTML5的一个持久化协议,实现了浏览器与服务器的全双工通信,同时也是跨域的一种解决方案。
WebSocket和HTTP都是应用层协议,都基于TCP协议。但是WebSocket是一种双向通信协议,在建立连接之后,WebSocket的server与client都能主动向对方发送或接收数据。同时,WebSocket在建立连接时需要借助HTTP协议,连接建立好后client与server之间的双向通信就与HTTP无关了。
Socket.io(封装了WebSocket)
前端:
<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.getElementByTagName('input')[0].onblur = function(){
socket.send(this.value);
};
</script>
后台:
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 ai 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.');
});
})
postMessage
如果两个网页不同源,就无法拿到对方的DOM。典型例子:iframe窗口和window.open方法打开的窗口。
html5引入了一个全新的API:跨文档通信API。这个API为window对象新增了一个window.postMessage方法,允许跨窗口通信。
postMessage方法的第一个参数是具体的信息内容,第二个参数是接收消息的窗口的源(origin),即“协议+域名+端口”。也可以为*,表不限制域名,向所有窗口发送。
发送信息页面:http://localhost:63342/index.html
<html lang="en">
<head>
<meta charset="UTF-8"/>
<title>跨域请求</title>
</head>
<body>
<iframe src="http://localhost:3000/users/reg" id="frm"></iframe>
<input type="button" value="OK" onclick="run()"/>
</body>
</html>
<script>
function run(){
var frm = document.getElementById("frm");
frm.contentWindow.postMessage("跨域请求信息","http://localhost:3000");
}
</script>
接收信息页面:http://localhost:3000/message.html
window.addEventListener('message',function(e){
console.log(e.data);
},false);