从不同的域操作 iframe

Posted

技术标签:

【中文标题】从不同的域操作 iframe【英文标题】:manipulate iframe from a different domain 【发布时间】:2018-11-30 00:11:07 【问题描述】:

就上下文而言,我正在为我的网站设计一个 Ionic 移动应用程序。但是,我不认为这个问题仅限于 Ionic 框架。

在我的应用程序中,我想显示一个全宽、全高的 iframe,从我的网站加载其中一个页面。这很简单:

<iframe id="myFrame" src="https://example.com/" style="height:100%;width:100%"></iframe>

但是,我现在希望能够从 iframe 中“修剪”或“隐藏”内容(类似于 this 示例)。在一个 iframe 中,我只想修剪导航栏(一个特定的命名 div)。在另一个 iframe 中,我实际上想剪掉页面内特定命名 div 内的所有内容。

我已经看到使用 jQuery “加载” 函数对同一域中的站点进行此操作。但是,对于该应用程序,我很确定我需要将 iframe 源视为一个单独的域,即使我拥有该站点并且该应用程序旨在访问该站点。

我使用 jQuery Ajax 看到了看起来很有希望的答案 here,但我需要更多的指针来执行它。

任何关于如何做到这一点的提示将不胜感激!

【问题讨论】:

【参考方案1】:

我认为这在不同来源的网站之间是不可能的。所提出的方法的主要问题不是 CORS,而是跨站点脚本。但是,可以使用postMessage() 将消息从父窗口发送到 iframe,执行隐藏在 iframe 源中的 javascript 代码。然后这个 javascript 可以操作页面中的元素。

这是我最终要工作的解决方案:

父窗口

var frame = document.getElementById('myFrame').contentWindow;

sendMessage = function(e) 
    frame.postMessage('secret command', 'https://endpoint.com');


<iframe data-tap-disabled="true" id="myFrame" src="https://endpoint.com/index.php" onload="sendMessage()"></iframe>

子(在 iframe 中加载的页面)包含此脚本:

<script>
window.onload = function() 
    // A function to process messages received by the window.
    function receiveMessage(e) 
        if (e.data == "secret command")
            //put code here to maniuplate page elements however desired
        else
            return;
    

    // Setup an event listener
    window.addEventListener('message', receiveMessage);

</script>

最终的结果是,在 iframe 中加载的页面可以根据从父窗口传递的命令以某种方式显示。对于我的使用,iframe 中加载的页面在从我的应用程序中加载时隐藏导航栏。

【讨论】:

【参考方案2】:

这绝对是可能的,但是您会遇到 CORS 问题,因此您需要牢记这一点。您必须记住,不会添加任何脚本或包含,因此为了获得最佳体验,请在运行此之前加载所有脚本和包含的页面上托管此内容。你可以看到一个超级基本的例子here 但是你会得到一个 CORS 错误,所以要看到它工作你需要安装 chrome CORS 插件并激活它。

你会看到调用很简单

$('#test').load('https://***.com/questions/50955345/manipulate-iframe-from-a-different-domain #question'); 

使用#标签表示要加载的内容的id。因此,如果您想加载 id 为“MySuperCoolAndInterestingDiv”的 div,只需在 URL 末尾添加“#MySuperCoolAndInterestingDiv”,URL 和主题标签之间的空格很重要,不要忘记。

【讨论】:

您好。我可以让您的代码与 CORS 插件一起使用,但问题是 A)我如何删除一个 div(即使站点来自同一个域,仍然会出现错误!link 和 B)我如何只显示一个 div 但保留格式?有没有办法将整个页面和脚本加载到隐藏变量中并且只显示有问题的 div?或者如何加载页面的所有脚本,以便 div 保留正确的格式? 这两个页​​面都是从您的域加载的吗?有了这个要求,CORS 将是一个真正的麻烦。如果这两个页面都是从您的域加载的,那么创建一个较小的页面会更容易,该页面仅显示您想要的信息及其样式,然后将其加载到 iFrame 中。保留 div 中的样式将是一场噩梦,需要编写大量特定的 css 来定位 div 中的元素。 不,将在 iframe 中加载网站的页面将托管在 Ionic 移动应用程序中。这会使它成为“origen:null”吗?有人告诉我,在 Chrome 上测试时出现的 CORS 问题不应该是实际应用程序中托管的网页的问题。 所以你的页面(我们称之为 index.htm),在你的 Iconic 移动应用程序中,会从某个站点加载另一个页面(比如说theirsite.com/info.htm)?并且您只希望 theirsite.com/info.htm 中的某个 div 在 index.htm 中呈现,但保留 theirsite.com 中的所有样式? 没错。是否有从 iframe 网站加载所有 CSS 样式和脚本的脚本或方法?

以上是关于从不同的域操作 iframe的主要内容,如果未能解决你的问题,请参考以下文章

当 iframe 在不同的域 iframe 中时,获取相同域 iframe 的高度?

在 iframe 中设置 cookie - 不同的域

跨域解决方案

什么 CSP 子 iframe 从其父 iframe 继承?

从不同域的 iframe 滚动到父级顶部

允许子 iframe 从不同域调用其父窗口上的函数