上周被提出一个在项目页面嵌套别人网站两个页面的需求,后经过 demo 测试跟网上查找,最终推翻了这个嵌套方案的需求。稍微总结下出来,给同样需求的人少点弯路。
iframe 嵌套展示是第一步
嵌套别的页面很简单,直接把被嵌套页面的 url 设置成 src 的值,例如: ,假如能展示出页面来就很好办了,用 iframe 自带的属性跟使用自己页面的 css、js,把嵌套的页面展示成自己想要的样子。但不展示出来恐怕就难办了,因为这个原因往往是被嵌套页面决定的,自己页面很难改变。
展示不出来很多情况是:xxx.xxx.xxx 拒绝了我们的连接请求!
这个拒绝不属于跨域问题,因为同源策略里允许 iframe、link、img、script 标签跨域。
这个根本原因是我们请求的 document 里返回的 X-Frame-Options(在 response headers 里)决定的。X-Frame-Options 有三个值: DENY、SAMEORIGIN、ALLOW-FROM。当是 deny 值时,代表任何网站页面都不能嵌套此页面,嵌套了就会出现上面的拒绝连接的提示;当是 sameorigin 值时,代表只能跟嵌套页面同域名时才能嵌套,否则同样拒绝嵌套;allow-from 值已被弃用,之前相当列白名单的功能;当请求的页面不设置这个属性时,代表次页面能被嵌套。( 需注意被嵌套的页面是否设置了 frame-ancestors 属性,因为浏览器可能废弃了 X-Frame-Options 属性,转变支持 Content-Security-Policy HTTP 响应头的 frame-ancestors 属性) - - 参考文档 mdn
所以通过被嵌套页面请求返回的属性,可以大体上判断是否能嵌套此页面了。对于 sameorigin 值时,网上讲的能通过请求代理伪装成同域名的请求,估计能行,可能麻烦些,需要后端配合设置。
iframe 交互是第二步
iframe 能够嵌套展示别人页面,并不代表自己页面能跟别人页面互相传递数据进行交互。互相传递数据就涉及到跨域问题了,其实就是浏览器同源策略引起的问题,限制了 访问数据(storage、cookie、indexedDB)、操作 dom、ajax 请求。访问数据限制常用的是 postMessage 来解决,postMessage 是 html5 的 api,其允许来自不同源的脚本采用异步方式进行通信。这种通信交互需要两个页面的开发人员约定配合,不是单独一方就能完成的交互。