业务背景:公司业务系统付款申请模块新增发票引入功能,新增按钮弹窗嵌入第三方发票校验页面,用于验证发票的真实性、发票抬头、税号准确性。
问题
第三方发票页面是一个域名地址,在第三方Demo(静态html页面)代码中分别使用内联框架(iframe)和打开新窗口(window.open)显示第三方页面,但是内联框架方式的代码被注释掉了。去掉注释试后试了一下效果,发现内联框架无法打开页面,弹窗方式可以。
<div id="modal" style="width: 1200px; height: 700px; display: none; position: fixed; top: 100px; left: 300px; background-color:#fff; z-index: 9999;">
<iframe id="iframe" style="width: 1150px; height: 600px;padding:2px; border:1px solid #ccc;"></iframe>
</div>
// 打开弹框
$("#open").click(function() {
var url="第三方页面";
$("#iframe").attr("src",);
return true;
});
内联框架无法打开页面的原因是因为跨域了,如图
而在实际业务中,如果使用打开新窗口方式的明显具有以下缺点:
1)导入失败无法立即看到;
2)导入成功无法自动关闭导入页面 ,
3)每次点击“发票云”按钮后 上一次打开的发票云页面就失效了 要使用最新的。
4)嵌入页面在展示效果、数据交互、页面控制上都比打开新窗口要好
由此本文展开展开对iframe嵌入页面的实践,以及对跨域问题的分析和验证。
跨域
跨域是指前端页面尝试向后端API请求资源、数据时,如果前端和后端不在同一个域下,浏览器就会组织这种跨域请求,以保护用户隐私和数据安全。
浏览器页面访问系统资源需要同源,协议、域名和端口都要相同,否则就是跨域。即HTTP和HTTPS不能互相请求,不同域名、端口都不能互相请求。因此静态页面使用内联框架直接访问第三方页面就提示了跨域。window.open的方式是在新窗口中打开URL,所以不会跨域。
解决
如何解决呢? 由于需求是请求页面而不是接口请求,以及项目系统框架的限制,这里是不能用JSONP、CORS、代理等方式的。而我们当前遇到的问题又是跨域问题,所以我们可以换个思路来解决它——不让它跨域是不是就可以了呢?(这里是充分研究过第三方域名地址的,其实就是客户私域的域名)
不让它跨域,就是让本地站点和第三方地址属于同一个协议、域名、端口,至少让浏览器认为他们是同一个域。做法如下:
- 将demo.html 发布到IIS发布网站,此时可以用localhost+端口访问到页面;
- 本地host添加 IP 到第三方域名映射
- 使用域名方式打开IIS站点重试
经过这种方式验证后真的就打开了!!! 因此实际本地开发过程中只需按照正常方式来开发,测试的时候将本地加入hosts映射,使用域名方式测试即可,部署到客户测试环境后也能正常使用。
总结
当系统内嵌跨域页面时,如果第三方域名都是私域域名,可以考虑使用添加hosts域名映射的方式解决“跨域”问题,让浏览器不会判定“跨域请求”。