您的位置:

跨域解决方案

一、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!');
  });
});