一、JSONP
JSONP全称为JSON with Padding(填充式JSON或参数式JSON),是一种跨域数据访问的解决方案。它通过插入一个script标签,让服务器返回一段JavaScript代码。JSONP的原理是利用script标签没有跨域限制的漏洞,通过script标签加载数据,由于服务端的数据是被包裹在回调函数中的,因此客户端可以通过回调函数来获取数据。JSONP的优点是兼容性好,可跨浏览器访问
// 前端代码
function callback(data) {
console.log(data);
}
let script = document.createElement('script');
script.src = 'http://www.example.com/api?id=1&callback=callback';
document.head.appendChild(script);
// 后端代码
let data = {
name: '张三',
age: 18,
gender: '男'
}
let jsonpStr = `callback(${JSON.stringify(data)})`;
res.end(jsonpStr);
二、CORS
CORS是Cross-Origin Resource Sharing缩写,即跨域资源共享。它是由W3C标准制定的,是一种允许浏览器向跨源服务器发出请求,从而克服了AJAX只能同源使用的限制。CORS通信与同源的AJAX通信相比,需要浏览器和服务器同时支持。其原理是在请求头中添加Origin字段,服务器端返回的响应头中,必须有Access-Control-Allow-Origin字段,用于指定允许的来源域名,如果所有来源都允许,则可以设置为“*”。
// 前端代码
let xhr = new XMLHttpRequest();
xhr.open('GET', 'http://www.example.com/api?id=1');
xhr.setRequestHeader('Content-Type', 'application/json');
xhr.onload = function() {
console.log(xhr.responseText);
};
xhr.send();
// 后端代码
app.all('*', function(req, res, next) {
res.header('Access-Control-Allow-Origin', '*');
res.header('Access-Control-Allow-Headers', 'X-Requested-With');
res.header('Access-Control-Allow-Methods', 'PUT,POST,GET,DELETE,OPTIONS');
next();
});
三、代理服务器
代理服务器也是一个常见的跨域解决方案,其原理是通过在服务器端设置代理,将请求先发送给代理服务器,由代理服务器再发送给目标服务器,然后再将结果返回给客户端,这样客户端就不用直接与目标服务器进行通信了。代理服务器的优点是可以在服务器端进行安全性控制,可以缓存数据,减轻目标服务器的负担。
// 前端代码
let xhr = new XMLHttpRequest();
xhr.open('GET', '/api?id=1');
xhr.setRequestHeader('Content-Type', 'application/json');
xhr.onload = function() {
console.log(xhr.responseText);
};
xhr.send();
// 后端代码
app.get('/api', function(req, res, next) {
request('http://www.example.com/api?id=' + req.query.id, function(error, response, body) {
if (!error && response.statusCode == 200) {
res.send(body);
} else {
res.send(error);
}
})
});
四、Nginx反向代理
如果项目中使用了Nginx作为Web服务器,则可以使用Nginx作为反向代理,来解决跨域问题。其原理是在Nginx的配置文件中加入反向代理的配置,将客户端的请求发送给Nginx服务器,由Nginx服务器再将请求转发给目标服务器,然后再将结果返回给客户端。
// Nginx配置文件
location /api/ {
proxy_pass http://www.example.com/api/;
proxy_set_header Host $host;
proxy_set_header X-Real-IP $remote_addr;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
}
五、WebSocket
WebSocket是HTML5中新增的一种全双工通信协议,它可以在浏览器与服务器之间建立持久性的连接,实现实时通信。WebSocket协议的优点是可以避免HTTP协议的限制,不受跨域限制,使用更方便,传输更快捷。它原理是通过在HTTP/HTTPS协议上建立WebSocket协议,实现双向通信。
// 前端代码
let socket = new WebSocket('ws://www.example.com:8080');
socket.onopen = function() {
socket.send('Hello Server!');
};
socket.onmessage = function(event) {
console.log(event.data);
};
// 后端代码
let WebSocketServer = require('ws').Server;
let wss = new WebSocketServer({port:8080});
wss.on('connection', function(socket) {
socket.on('message', function(message) {
console.log('received: ', message);
socket.send('Hello Client!');
});
});