先对自己说两句闲话,变懒了,很久没有记录自己的工作了,希望不忘初衷。
最近我有这样一个需求,我们是设备软件公司,因此有一个功能就是修改自己的管理口IP和端口,要求修改完成后跳转到新的页面,这里会出现一个问题,就是原有的页面上要通信新的IP和端口,这就涉及到跨域问题,跨域问题解决网上有很多种,我在此只记录我使用过的两种。
我们工程的架构是前端通过Apache反向代理发送到后端,因此cors这种跨域方法,我们应该对Apache做cors的配置(原以为是后端做cors配置)还有一些相关配置,大家百度就好,需要在Apache上添加以下代码:
<Directory />
Header set Access-Control-Allow-Origin *
</Directory>
配置后重启Apache,我们还需要后端配合做一个事情,因为这个时候我们能够调用新的IP的url,但是浏览器检测到跨域的时候,会发送一个请求方式为OPTIONS的预检查url,这个url需要后端取消头信息检测,然后返回成功后,浏览器才会发送一个真实的url,这样我们的跨域访问才会成功
这样处理过后我们就可以在任何页面里调用我们的IP,说实话是很不安全的,当然 * 是可以改为一个固定的url,这样只能在固定url页面里跨域调用我们的功能,但是这个不适用于我们本次需求,或者能做但是比较麻烦,因为这样我要麻烦后端先把这个*修改为用户的新的IP,然后他再修改底层IP。所以放弃这个方法
然后我需要一种不需要牺牲安全性的跨域方式,针对于修改管理口IP或者端口的业务处理方法。那就是通过iframe实现跨域,具体我们要在原来的页面给一个隐形的iframe框,然后在下面给一个a标签,把target属性指向iframe的name属性,目的就是点击a标签的时候新建的页面会在iframe里面展示,而不是新开一个浏览器窗口。然后我们监测iframe里面页面的加载,就能知道修改的新的IP或者端口是否成功,其中的曲折是我最开始只是监测了iframe的加载,在谷歌浏览器中连续加载八次左右不成功的url就会被返回失败的页面,所以我们如果只监测iframe的加载,在八次的时候,我们会获取到错误监测,因为真实的url本没有通信成功,而是浏览器自己返回的失败页面,所以我们需要监测iframe页面加载的内容,很不幸我试了很多次没有获取到里面的dom,所以只能让iframe的通信成功后的页面给我的当前页面发送一个消息,用window.parent.postMessage('ok','*')发送,
window.addEventListener('message',function (e) {if(e.data=='ok'){}})监测,下面我展示相关代码:
//本代码是放在需要做跳转的配置页面的HTML里面
<div style="z-index: 999;display: none;position: absolute;">
<iframe id="login-frame-1" name="login-frame-1"></iframe>
<a href="#" id="login-a" target="login-frame-1">jump</a>
</div>
//vue数据初始化
data() {
return {
loginGetatt:0,
loginReady: false,
cancle_setTimeOut:undefined,
}
},
// 本代码放在页面加载成功后执行,vue放在mounted里面//loginReady 是我们加载成功后状态标签,原始状态需要设置为false,vue在data()里面设置
window.addEventListener('message',function (e) {
console.log(e)
if(e.data=='ok'){
self.loginReady = true
}
})
//这个代码是放在修改IP或者端口的API之前的
setTimeout(function () {
//这个里面可以添加是不是需要跳转的判断逻辑,因为IPV4页面修改ipv6地址是不需要跳转的
//url为用户修改的新的url地址
document.getElementById('login-a').href = url+'/login'
self.loginGet(url)
},3000)
//这个逻辑就是每隔3秒点击a标签,如果判断self.loginReady为true说明新IP的页面加载成功,或者超时直接让当前窗口跳转新URL
loginGet(url){
let self = this
self.loginGetatt++ //self.loginGetatt初始值为0,vue在data()里面设置
self.cancle_setTimeOut=setTimeout(function () {
document.getElementById('login-a').click()
if(self.loginReady||self.loginGetatt>30){\
window.location.href=url
}else{
self.loginGet(url)
}
},3000)
},
//vue销毁此次绑定的setTimeout和监听事件
destroyed(){
let self = this
clearTimeout(this.cancle_setTimeOut);
window.removeEventListener('message',function (e) {
console.log(e)
if(e.data=='ok'){
self.loginReady = true
}
})
},
//这个方法放在新跳转页面的js中,只要加载页面完毕后就会向window发送消息,以此来判断页面在iframe里面加载成功
function checkout_iframe() {
window.parent.postMessage('ok','*')
}
总结,修改Apache配置在本次需求中不合适,但是如果我们能够保证后端修改IP的速度,也就是再连续发送新的IP八次以内,我们最好使用iframe绑定onload的事件,因为我们在修改一个没有登录过的IP的时候,即使后端修改成功后,火狐或者谷歌也会在iframe的框里加载拦截页面,所以不能向当前页面发送成功消息,如果我们用iframe的onload事件,我们就能判断新页面加载成功,但是必须要在八次通信之内,(火狐不存在通信八次左右失败后加载失败页面)
来源:CSDN
作者:卡塔库栗
链接:https://blog.csdn.net/lixiwoaini/article/details/104037354