前端跨域问题解决过程记录

橙三吉。 提交于 2020-01-20 02:12:50

    先对自己说两句闲话,变懒了,很久没有记录自己的工作了,希望不忘初衷。

    最近我有这样一个需求,我们是设备软件公司,因此有一个功能就是修改自己的管理口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事件,我们就能判断新页面加载成功,但是必须要在八次通信之内,(火狐不存在通信八次左右失败后加载失败页面)

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!