跳至主要內容
  • Hostloc 空間訪問刷分
  • 售賣場
  • 廣告位
  • 賣站?

4563博客

全新的繁體中文 WordPress 網站
  • 首頁
  • 一个关于 iframe 很艹蛋的前端需求
未分類
4 2 月 2021

一个关于 iframe 很艹蛋的前端需求

一个关于 iframe 很艹蛋的前端需求

資深大佬 : biguokang 2

业务是这样的

我们用 iframe 调用了 [被调用方] 的页面,然后 [被调用方] 页面一些 a 标签的 target 是“blank”的,这就导致点击他们的 a 标签会打开新的 tab

而现在的需求是,在 iframe 里的任何操作,都 [ [不允许弹出新 tab 或者新窗口] ] ,如果 [被调用方] 的页面的确是要打开新 tab 的,那就改为在本地页面跳转。

正常来说是无法实现的,因为跨域,而且 [被调用方] 肯定不会改代码的,所以只能写了个浏览器插件,通过注入代码的形式强行把网页里所有的 a 标签的 target 改为 self,这样 a 标签就全都是本地跳转

但是 [被调用方] 网页里面的业务不一定全是用 a 标签来打开新 tab,他们可能一些业务是用 js 来打开新 tab 的(类似于 window.open 这种,我尝试在插件里把 window.open 覆写成 window.location.href,但也只是部分按钮实现了,有些还是会跳出新页面)

现在问题如下: 1.被调用方是肯定不会改代码的,这个无解

2.已经能通过写浏览器插件的方式来注入代码强改客户代码的 a 标签(因为被调用方是不同域的,而且非互联网项目,装插件的设备也就那么几台,也不麻烦)

3.不能说这玩意不能做,因为项目跑在超高分大屏(电影院银幕大小)上,网页全屏显示,他有这种需求是因为打开新 tab 会强制关掉网页全屏,导致观感不好

然后如何完美实现??(虽然以我的见解这玩意是无法实现的,用浏览器插件来搞已经很仁至义尽了)

大佬有話說 (51)

  • 資深大佬 : SlipStupig

    父页面往子页面做事件注入,监听点击事件并且 Hook 掉一些事件和函数,在父页面创建一个事件监听器,然后定义一个 receiveMessage 函数,子页面通过 window.postMessage 做跨域通信,父页面就能知道具体的点击事件了,新 tab 可以先请求页面然后覆盖掉原始的 body,这要不用跳转直接刷新了,思路仅供参考哈

  • 資深大佬 : Osk

    chrome 的 –kiosk 模式试试?

  • 資深大佬 : tanranran

    写个浏览器的壳?

  • 資深大佬 : cheng6563

    服务端也可以搞个[被调用方] 的代理程序,然后注入代码。可能比浏览器插件好用点?

  • 資深大佬 : meepo3927

    用 Electron ? 没实践过,只是提供一个思路。

    或者 nginx 做代理,把 iframe 代理到 [被调用方] 的域上,这样 iframe 就是同域了,不知能否解决。

  • 資深大佬 : yoshiyuki

    nginx 或者 nodejs 来代理被调用页面,使用 replace 把 target 替换掉

  • 主 資深大佬 : biguokang

    @SlipStupig 一开始和你想法一样,但是实际项目情况,注入不了,因为子页面是跨域的,contentDocoument 是 null 的,直接操作 contentWindow 直接报跨域错误,所以后来才想着写浏览器插件来注入代码才改的了子页面的逻辑。。。。。而且你想使用 postMessage 来通信,需要改被调用方的代码来接收的,但是实际场景被调用方的代码他们是不能改的。。。。如果可以改被调用方的业务代码,也不会有那么多事了

  • 資深大佬 : zenxds

    有些还是会跳出新页面?要具体看下有些是什么情况,比如 document.createElement 创建的 a 标签,需要把 document.createElement 也重写了

  • 資深大佬 : mknightoy

    浏览器关掉跨域保护不就完了么,反正都是展示用的不需要跨域保护

  • 資深大佬 : SlipStupig

    @biguokang 关闭浏览器的跨域选项或者用 Nginx 做代理,都可以啊

  • 資深大佬 : agee

    自己做个套壳浏览器,就可以自己处理所有打开新窗口事件,这样不需要管网页上的代码了。理论上好像是这样,没具体试过。

  • 資深大佬 : winterx

    难道就只有我想知道为什么被调用方不肯改代码?

  • 資深大佬 : SakuraKuma

    支持 nginx 反代,把 target 都干掉
    除非额外有骚操作 js 跳转之类的

  • 主 資深大佬 : biguokang

    @winterx 我也想知道,但是人家就是那样,无解

  • 資深大佬 : stillyu

    设置浏览器禁止打开弹出窗口?

  • 資深大佬 : DrakeXiang

    有浏览器扩展强制在同一个 tab 打开新页面

  • 資深大佬 : SystemLight

    为什么不把 iframe 中内容读取出来,然后动态修改里面内容 再呈现呢 ?

  • 資深大佬 : msmmbl

    可以用 nw.js 的话,他有一个 new-win-policy 和 navigation 事件可以控制跳转行为。

  • 資深大佬 : leo108

    window.open = function(url) { location.href = url }
    window.open(‘https://v2ex.com’)

  • 資深大佬 : ciqulover

    既然都有浏览器插件了 咋还动不了 iframe 跳转逻辑呢?直接 intercept 掉 iframe 内的 script 加载返回体,正则全局替换 window.open,如果内联在 html 里的 script 代码,用 mutation observer 劫持替换就行。

  • 資深大佬 : musi

    其实 iframe 还有个 sandbox 属性可以设置 allow-popups

    详情左转 https://developer.mozilla.org/zh-cn/docs/web/html/element/iframe

  • 資深大佬 : Hanada

    为什么不考虑一下直接反向代理被调用方的网页,然后就可以根据需要进行改动了

  • 資深大佬 : zqx

    避免 iframe 的安全策略,就肯定不能用 iframe 了。
    可以在你的 js 里,把别人的 html 请求回来,解析并插入到自己的 DOM 中,再请求 css js,是 vue 或 react 或原生 js,按对应的逻辑执行。关键难点在于要拿到他的路由和状态管理,如果他没有在代码里显式导出给你,就很难拿到,需要从源码里找
    微前端的实现大概也是这个思路

  • 資深大佬 : sampeng

    这你都干…怼回去啊。怎么不让做个屏幕随着衣服颜色变色呢?

  • 資深大佬 : uiosun

    iframe 不是可以禁止跳转吗……就在基本配置里啊……

    是我没理解对需求,还是你好歹去看看文档啊……

  • 資深大佬 : zhw2590582

    Chrome 可以监听新页面打开事件,看能不能在打开的时候马上关闭,并 iframe 重定向

  • 資深大佬 : coderfuns

    iframe sandbox 属性,但是 ie9 前是不支持的。

  • 資深大佬 : GM

    自己写一个程序,内嵌 webview,不要用第三方浏览器,这样有 100%的控制权,随便搞。

  • 主 資深大佬 : biguokang

    @uiosun 老哥,我当然知道 iframe 是可以通过设置 sandbox 来禁止跳转,这个不用你教。。。问题是我的需求不是禁止跳转,而是把打开新窗口的逻辑改为在原地跳转

  • 主 資深大佬 : biguokang

    @coderfuns 这玩意我是有设置的,唯一的作用也就是禁止 iframe 页面打开新窗口而已,只不过满足不了需求,需求是把打开新窗口的操作变为原地跳转

  • 主 資深大佬 : biguokang

    @musi 这玩意我是有设置的,唯一的作用也就是禁止 iframe 页面打开新窗口而已,只不过满足不了需求,需求是把打开新窗口的操作变为原地跳转

  • 主 資深大佬 : biguokang

    @ciqulover 我是自己开发了一个浏览器插件,通过注入的方式解决了,说白了就是通过事件委托检测到点击了 a 标签后,然后禁止调 a 标签的行为,改为 window.location.href=xxx 就实现了。。。但只是解决了 a 标签的跳转逻辑,而 js 的跳转还没有

  • 資深大佬 : shaoyijiong

    我们有一个类似的需求 我们是在后端写一个代理服务 , 前端请求那个代理 , 代理请求对应的网页 ; 然后在代理服务里面写入自己的 js 代码 , 就可以修改原来的 html 元素里面的 a 标签了 ; 或者直接修改原始 html 也行
    后端使用的是 java 做的代理 https://github.com/mitre/HTTP-Proxy-Servlet

  • 資深大佬 : shaoyijiong

    也可以在嵌入的 js 中取消别人的点击事件

  • 資深大佬 : no1xsyzy

    用 Nginx 反代改成同域啊
    Aria2 的老技巧了(

  • 資深大佬 : dlllcs

    electron 可解

  • 資深大佬 : ArthurSS

    https://developer.mozilla.org/zh-CN/docs/Web/HTML/Element/iframe
    sandbox
    该属性对呈现在 iframe 框架中的内容启用一些额外的限制条件。属性值可以为空字符串(这种情况下会启用所有限制),也可以是用空格分隔的一系列指定的字符串。有效的值有:
    …
    allow-popups: 允许弹窗 (例如 window.open, target=”_blank”, showModalDialog)。如果没有使用该关键字,相应的功能将自动被禁用。
    …

  • 資深大佬 : mxT52CRuqR6o5

    不能改代码,那能不能看代码,遇到没拦截住的就具体看看代码里是咋跳的,就知道为啥没拦截到了

  • 資深大佬 : ArthurSS

    @ArthurSS #37 刚刚没看到上评论。。。

  • 資深大佬 : krapnik

    19 的方法解决不了嘛?

  • 資深大佬 : CODEWEA

    我做过类似的,用 postMessage 通信即可

  • 資深大佬 : lixiangzaizheli

    重写跳转注入不就好了

  • 資深大佬 : ganbuliao

    解决办法就是 : 劫持注入 js ,插件注入 js,套壳写浏览器,

  • 主 資深大佬 : biguokang

    @CODEWEA postMessage 无解,改不了被调用方的代码

  • 主 資深大佬 : biguokang

    @mxT52CRuqR6o5 被调用方的代码是 webpack 打包过的,变量名也被打包工具魔改了,基本无可读性

  • 資深大佬 : PineappleBeers

    我觉得你当前的需求用 4 和 19 的方法结合就来就可以解决。
    浏览器请求你的服务。
    服务从被调用方的地址获取到页面。
    从获取到的 html 里注入一个 script 标签,标签里的内容就是重写 window.open 。
    然后将注入后的页面返回浏览器。

  • 主 資深大佬 : biguokang

    @PineappleBeers 他们可能没看完我的问题,我问题里说了已经我已经 override 了 window.open,但也只是一部分生效而已。。。而且所有的 a 标签已经被我的注入代码改成 target=_self 了

  • 資深大佬 : zhuweiyou

    被调用方的页面 用服务端代理 + 改写

  • 資深大佬 : R18

    制作专用的浏览器呢?

  • 資深大佬 : autoxbc

    并不需要读懂对方代码,只要把能够进行地址跳转的函数全部覆盖一遍,大概一只手就能数过来

  • 資深大佬 : billccn

    想到我十年前做的老项目,当时是为一个触摸屏的工业设备做一些辅助功能,公司不想花钱去买厂家的 SDK,就要求利用内置的浏览器实现,最骚的就是偶尔要内嵌显示另一个网站,要可以交互,但是不能允许该网站弹窗或者影响宿主页面,这些是 iframe 做不到的(有这些功能那机子的内存也不够)。

    最后发现那个内置的浏览器可以支持 Java applets,就直接在网页里套了个 Java 版的 VNC 客户端,连接到服务器上一个无壳的 Chrome,弹窗什么的都只在服务器上进行,怎么也不会影响到客户端,而且客户端可以看到所有的效果。现在时代进步了,VNC 客户端可以直接用 JS 实现了。

文章導覽

上一篇文章
下一篇文章

AD

其他操作

  • 登入
  • 訂閱網站內容的資訊提供
  • 訂閱留言的資訊提供
  • WordPress.org 台灣繁體中文

51la

4563博客

全新的繁體中文 WordPress 網站
返回頂端
本站採用 WordPress 建置 | 佈景主題採用 GretaThemes 所設計的 Memory
4563博客
  • Hostloc 空間訪問刷分
  • 售賣場
  • 廣告位
  • 賣站?
在這裡新增小工具