js中的跨域解决方案

文章类型:Javascript

发布者:hp

发布时间:2023-03-01

一:原因

跨域是指从一个域名的网页去请求另一个域名的资源,因为浏览器有同源策略限制,必须保证协议+域名+端口相同,才能访问

主要限制Cookie、LocalStorage 和 IndexDB 无法读取。(2) DOM 无法获得。(3) AJAX 请求不能发送

二:方案

1:jsonp

只能Get请求,动态创建script,再进行跨域通信,主要组成由回调函数和数据,常用于减轻服务器压力,比如js,css。img资源等

<script src="https://baidu.com/5a1Fazu8AA54nxGko9WTAnF6hhy/su?wd=a&cb=show"></script>

function show(params) {
console.log(params);
}

2:cors

跨域资源共享,在服务端头部设置Access-Control-Allow-Origin

简单请求=> 浏览器直接发出CORS请求。就是在头信息之中,增加一个Origin字段

非简单请求=>对服务器有特殊要求的请求,比如请求方法、传递类型,会有一次预检请求(preflight)

Access-Control-Allow-Origin=>设置域名,*表示所有

Access-Control-Allow-Credentials=>表示是否运行发送Cookie

Access-Control-Expose-Headers=>拿取基本字段外的其他字段

Access-Control-Request-Method=>列出请求会用到那些方法

Access-Control-Allow-Methods=>表示服务器支持的所有跨域方法

Access-Control-Allow-Headers=>服务器支持的所有头信息字段

Access-Control-Allow-Credentials=>

Access-Control-Max-Age=>用来指定本次预检请求有效期

3:document.domain+iframe

只适用于主域相同,子域不同情况,两个页面都通过js强制设置document.domain为基础主域

  document.domain = 'a.com';
var user = 'admin';
alert('get js data from parent ---> ' + window.parent.user);

4:location.hash+ifrm

通过中间页面来进行相互通信

a
var iframe = document.getElementById('iframe');
// 向b.html传hash值
setTimeout(function() {
iframe.src = iframe.src + '#user=admin';
}, 1000);

// 开放给同域c.html的回调方法
function onCallback(res) {
alert('data from c.html ---> ' + res);
}
b
window.onhashchange = function () {
iframe.src = iframe.src + location.hash;
};
c
window.onhashchange = function () {
// 再通过操作同域a.html的js回调,将结果传回
window.parent.parent.onCallback('hello: ' + location.hash.replace('#user=', ''));
};


5:window.name+iframe

利用浏览器的特效,只要在同一个窗口,前一个网页设置了这个属性,后一个网页就可以读取它

  window.name = 'This is b.html data!';
var data = document.getElementById('myFrame').contentWindow.name;

6:postMessage

html5新增方法,第一个参数为具体信息内容,类型只能为字符串,第二个参数为接收消息的源,即协议+域名+端口

主要采用postMessage发送数据,onmessage 进行监听和接收数据

 let frame = document.getElementById('frame');
frame.contentWindow.postMessage('从a页面向b页面','http://localhost:4002');
window.onmessage = function (e) { //父窗口和子窗口都可以通过message事件,监听对方的消息。
console.log(e.data, 'a.html');
}

7:nginx

nginx配置代理服务器,域名保持相同,端口不同做跳板机

location / {
add_header Access-Control-Allow-Origin *;
proxy_pass http://www.cqhxb.com:8080; #反向代理
proxy_cookie_domain www.cqhxb.com www.cqhxb.com; #修改cookie里域名
index index.html index.htm;
}

8:nodejs中间件

启动一个代理服务器,实现数据的转发

app.use('/', proxy({
// 代理跨域目标接口
target: 'http://www.cqhxb1.com:8080',
changeOrigin: true,

// 修改响应头信息,实现跨域并允许带cookie
onProxyRes: function(proxyRes, req, res) {
res.header('Access-Control-Allow-Origin', 'http://www.cqhxb.com');
res.header('Access-Control-Allow-Credentials', 'true');
},

// 修改响应信息中的cookie域名
cookieDomainRewrite: 'www.cqhxb.com' // 可以为false,表示不修改
}));

9:webSocket/Socket.io

浏览器与服务器全双工通信,允许跨域通讯,ws://(非加密)和wss://(加密)

Socket.io采用on/send监听和发送数据,onmessage 接收数据

webSocket采用send/onmessage发送和监听数据

10:Proxy该服务器转发请求至目标服务器,得到结果再转发给前端

module.exports = {
devServer: {
host: '127.0.0.1',
port: 8080,
open: true,// vue项目启动时自动打开浏览器
proxy: {
'/api': { // '/api'是代理标识,用于告诉node,url前面是/api的就是使用代理的
target: "http://xxx.xxx.xx.xx:8080", //目标地址,一般是指后台服务器地址
changeOrigin: true, //是否跨域
pathRewrite: { // pathRewrite 的作用是把实际Request Url中的'/api'用""代替
'^/api': ""
}
}
}
}
}