bojue/bojue.github.io

前端跨域解决方案

bojue opened this issue · 0 comments

bojue commented

跨域

因为浏览器同源策略的存在,当资源的协议版本,域名,端口,子域名不同,而导致无法请求到其他源的资源的一些数据:

  • 读取不到Cookie,LocalSotrage的值
  • 不能获取DOM和JavaScript对象
  • Ajax请求不能通信

我们可以使用常见的如后端跨域,CORS等方案进行处理:

  • CORS
  • iframe + document.domain

父子类通信通过JavaScript设置document.domain变量实现通信

//父类
document.domain = 'iframe.com';
var val = 'parent';

//子页面
document.domain = 'iframe.com';
console.log( window.parent.val)
  • iframe + location.hash

通过监听window.onhashchange变化实现通信

 //a.html
var iframe = document.getElementById('iframe');
iframe.src = iframe.src + '#user=admin';

//b.html
var iframe = document.getElementById('iframe');
window.onhashchange = function () {
    iframe.src = iframe.src + location.hash;
};
  • iframe + window.name

window.name属性在不同域加载完成之后依旧存在,可以最多用来传递2MB的数据

  • 图片 Ping

动态创建图像可以用于图片Ping,是一种单项的通信方式,可以实现跨域请求,常见的应用常见:用户广告投放计算曝光率,点击率。

let img = new Image();
img.onload = img.onerror = function() {
    console.log('done!');
}
img.src = "https://www.baidu.com/test?params='github'";
  • JSONP

浏览器的同源策略,没有限制静态资源css,img,script的跨域请求,jsonp就是利用这个原理,动态的创建script实现跨域通信。

var script = document.createElement('script');
script.type = 'text/javascript';

script.src = 'url&callback=handleCallback';
document.head.appendChild(script);

function handleCallback(res) {
    console.log("res", res)
}

在服务器我们需要响应回调函数:

handleCallback({'message':'success'})
  • Node中间件代理

通过node启动代理服务器实现数据代理转发,可以同过cookieDomainRewrite参数修改响应头部cookie中的域名,写入当前的cookie实现登认证。

前端请求

var xhr = new XMLHttpRequest();
xhr.withCredentials = true;
xhr.open('get', 'http://www.domain1.com:3000/login?user=admin', true);
xhr.send();

下面是参考资料中的一个代理服务器器。

var express = require('express');
var proxy = require('http-proxy-middleware');
var app = express();

app.use('/', proxy({
    target: 'http://www.domain2.com:8080',
    changeOrigin: true,

    onProxyRes: function(proxyRes, req, res) {
        res.header('Access-Control-Allow-Origin', 'http://www.domain1.com');
        res.header('Access-Control-Allow-Credentials', 'true');
    },

    cookieDomainRewrite: 'www.domain1.com' 
}));

app.listen(3000);
console.log('Proxy server is listen at port 3000...');
  • WebSoket 跨域

WebScoket是H5提供的全双工通信协议,可以使用websocket协议实现跨域,一般使用socket.io做兼容性处理。

参考