防止浏览器中的 iframe 缓存
Posted
技术标签:
【中文标题】防止浏览器中的 iframe 缓存【英文标题】:Preventing iframe caching in browser 【发布时间】:2011-02-08 12:51:18 【问题描述】:如何防止 Firefox 和 Safari 缓存 iframe 内容?
我有一个简单的网页,其中包含指向不同网站页面的 iframe。外页和内页都有 HTTP 响应标头以防止缓存。当我在浏览器中单击“返回”按钮时,外部页面可以正常工作,但无论如何,浏览器总是会检索 iframe 页面的缓存。 IE 运行良好,但 Firefox 和 Safari 给我带来了麻烦。
我的网页看起来像这样:
<html>
<head><!-- stuff --></head>
<body>
<!-- stuff -->
<iframe src="webpage2.html?var=xxx" />
<!-- stuff -->
</body>
</html>
var
变量总是变化的。尽管 iframe 的 URL 已更改(因此,浏览器应该向该页面发出新请求),但浏览器只是获取缓存的内容。
我检查了往返的 HTTP 请求和响应,我注意到即使外部页面包含 <iframe src="webpage2.html?var=222" />
,浏览器仍然会获取 webpage2.html?var=111
。
这是我迄今为止尝试过的:
使用随机变量值更改 iframe URL 向外部网页添加 Expires、Cache-Control 和 Pragma 标头 向内部网页添加 Expires、Cache-Control 和 Pragma 标头我无法使用任何 javascript 技巧,因为我被同源策略阻止了。
我的想法已经不多了。有谁知道如何阻止浏览器缓存 iframed 内容?
更新
我按照 Daniel 的建议安装了 Fiddler2 进行另一次测试,不幸的是,我仍然得到相同的结果。
这是我进行的测试:
-
外页在JSP中使用
Math.random()
生成随机数。
外页在网页上显示一个随机数。
外页调用iframe,传入一个随机数。
内页显示随机数。
通过这个测试,我可以准确地看到哪些页面正在更新,哪些页面被缓存了。
视觉测试
为了快速测试,我加载页面,导航到另一个页面,然后按“返回”。结果如下:
原始页面:
外页:0.21300034290246206 内页:0.21300034290246206离开页面,然后回击:
外页:0.4470929019483644 内页:0.21300034290246206这表明内部页面正在被缓存,即使外部页面在 URL 中使用不同的 GET 参数调用它。出于某种原因,浏览器忽略了 iframe 正在请求新 URL 的事实;它只是加载旧的。
提琴手测试
果然,Fiddler 确认了同样的事情。
(我加载页面。)
外页被调用。 HTML:
0.21300034290246206
<iframe src="http://ipv4.fiddler:1416/page1.aspx?var=0.21300034290246206" />
http://ipv4.fiddler:1416/page1.aspx?var=0.21300034290246206 被调用。
(我离开页面然后回击。)
外页被调用。 HTML:
0.4470929019483644
<iframe src="http://ipv4.fiddler:1416/page1.aspx?var=0.4470929019483644" />
http://ipv4.fiddler:1416/page1.aspx?var=0.21300034290246206 被调用。
嗯,从这个测试来看,网络浏览器似乎没有缓存页面,但它正在缓存 iframe 的 URL,然后对该缓存的 URL 发出新请求。但是,我仍然对如何解决这个问题感到困惑。
有人对如何阻止网络浏览器缓存 iframe URL 有任何想法吗?
【问题讨论】:
+1 -- 你的写作很好地捕捉到了痛苦。 感谢您对问题的非常详细的解释,这 100% 正是我在网站上遇到的情况。七年过去了,firefox bug report 仍然存在。 这能回答你的问题吗? Refresh iFrame (Cache Issue) 【参考方案1】:你安装Fiddler2了吗?
它可以让您准确地看到请求的内容、发回的内容等。浏览器真的会针对不同的 URL 访问其缓存,这听起来不太合理。
【讨论】:
感谢 Fiddler2 的提示。现在我知道浏览器没有缓存 iframe 内容;它只是缓存 iframe URL。但是,我仍然很困惑,我不知道为什么浏览器会忽略新页面的 iframe URL 而只是使用旧 URL。【参考方案2】:使 iframe 的 URL 指向您网站上的一个页面,该页面充当代理来检索和返回 iframe 的实际内容。现在您不再受同源策略的约束(编辑:不会阻止 iframe 缓存问题)。
【讨论】:
这不会阻止缓存。 @baash05 我从来没有声称它确实如此;我说它避免了同源政策。 True.. 但是操作标题显示为“防止浏览器中的 iframe 缓存”,如果您的答案不能阻止浏览器中的 iframe 缓存,那么这并不是真正的答案。很高兴知道,但对于希望防止缓存的人来说仍然不是一个好建议。 OP 正在寻求解决缓存问题和避免同源策略。部分答案总比没有好:) 吐司总是果酱面朝下 :)【参考方案3】:如果您想真的疯狂,您可以将页面名称实现为始终解析为同一页面的动态 url,而不是查询字符串选项?
假设您在办公室,请检查网络级别是否正在进行任何缓存。相信我,这是一种可能。您的 IT 人员将能够告诉您是否有围绕 HTTP 缓存的任何网络基础架构,尽管这仅发生在 iframe 上,这不太可能。
【讨论】:
【参考方案4】:这是 Firefox 中的一个错误:
https://bugzilla.mozilla.org/show_bug.cgi?id=356558
试试这个解决方法:
<iframe src="webpage2.html?var=xxx" id="theframe"></iframe>
<script>
var _theframe = document.getElementById("theframe");
_theframe.contentWindow.location.href = _theframe.src;
</script>
【讨论】:
今天 27.2.2014 我很高兴找到这个帖子,我认为它可以通过服务器端无缓存来解决。 FF 27 仍然有这个错误。 7.8.2014 - 8 年后,仍未修复。 这也适用于 srcdoc 属性,太奇怪了……太棒了,我发现了这个。 我在 Chrome 中发现了同样的缓存问题,两行 JavaScript 解决了它。谢谢! 哇,遇到了完全相同的问题。特定于 Firefox - 在 IE、Chrome 等中运行良好。感谢@caleb。不敢相信这已经持续了这么久。【参考方案5】:这是 Firefox 3.5 中的一个错误。
看看.. https://bugzilla.mozilla.org/show_bug.cgi?id=279048
【讨论】:
【参考方案6】:我稍后在我的应用程序中设置了 iframe src 属性。要在应用程序开始时摆脱 iframe 中的缓存内容,我只需这样做:
myIframe.src = "";
... js 代码开头的某处(例如在 jquery $() 处理程序中)
感谢 http://www.freshsupercool.com/2008/07/10/firefox-caching-iframe-data/
【讨论】:
【参考方案7】:要让 iframe 始终加载新内容,请将当前 Unix 时间戳添加到 GET 参数的末尾。然后浏览器将其视为“不同”请求,并将寻找新内容。
在 Javascript 中,它可能看起来像:
frames['my_iframe'].location.href='load_iframe_content.php?group_ID=' + group_ID + '×tamp=' + timestamp;
【讨论】:
【参考方案8】:我已经能够通过在 iframe 上设置一个唯一的 name
属性来解决这个错误 - 无论出于何种原因,这似乎破坏了缓存。您可以使用您拥有的任何动态数据作为name
属性 - 或者只是使用您正在使用的任何模板语言中的当前 ms 或 ns 时间。这是一个比上面更好的解决方案,因为它不直接需要 JS。
在我的特殊情况下,iframe 是通过 JS 构建的(但您可以通过 PHP、Ruby 等来做同样的事情),所以我只使用Date.now()
:
return '<iframe src="' + src + '" name="' + Date.now() + '" />';
这修复了我测试中的错误;可能是因为内部窗口中的window.name
发生了变化。
【讨论】:
截至 2015 年底,此答案适用于 Chrome、Firefox 和 Safari。【参考方案9】:在尝试了所有其他方法后(除了对 iframe 内容使用代理),我找到了一种防止 iframe 内容缓存的方法,来自同一域:
使用.htaccess
和重写规则并更改iframe src
属性。
RewriteRule test/([0-9]+)/([a-zA-Z0-9]+).html$ /test/index.php?idEntity=$1&token=$2 [QSA]
我使用它的方式是 iframe 的 URL 最终看起来是这样的:example.com/test/54/e3116491e90e05700880bf8b269a8cc7.html
其中 [token] 是一个随机生成的值。此 URL 可防止 iframe 缓存,因为令牌永远不会相同,并且 iframe 认为这是一个完全不同的网页,因为单次刷新会加载一个完全不同的 URL:
example.com/test/54/e3116491e90e05700880bf8b269a8cc7.html
example.com/test/54/d2cc21be7cdcb5a1f989272706de1913.html
两者都指向同一个页面。
您可以使用$_SERVER["QUERY_STRING"]
访问您的隐藏网址参数
【讨论】:
为我工作 - 谢谢! @QuinnFinney 很高兴这对其他人有用。这个问题我花了几天时间才解决:) 是的 - 我也是!哈哈哈【参考方案10】:截至 2016 年 3 月 17 日,我在最新的 Chrome 以及 Mac OS X 上的最新 Safari 中发现了这个问题。上述修复都没有对我有用,包括将 src 分配为空然后返回某个站点,或者添加一些随机命名的“name”参数,或者在hash之后的URL末尾添加一个随机数,或者在分配src之后将内容窗口href分配给src。
就我而言,这是因为我使用 Javascript 来更新 IFRAME,并且只切换 URL 中的哈希值。
在我的情况下,解决方法是我创建了一个临时 URL,该 URL 具有 0 秒元重定向到该其他页面。它发生得如此之快,以至于我几乎没有注意到屏幕闪烁。另外,我将中间页面的背景颜色设置为与其他页面相同,因此您不会注意到它。
【讨论】:
【参考方案11】:我在 2016 年使用 ios Safari 时也遇到了这个问题。似乎对我有用的是
给 iframe src 一个 GET 参数和一个像这样的值 <iframe width="60%" src="../other/url?cachebust=1" allowfullscreen></iframe>
【讨论】:
【参考方案12】:正如你所说,这里的问题不是 iframe 内容缓存,而是 iframe url 缓存。
截至 2018 年 9 月,该问题似乎仍出现在 Chrome 中,但未出现在 Firefox 中。
我已经尝试了很多事情(添加一个不断变化的 GET 参数,在 onbeforeunload 中清除 iframe url,使用 cookie 检测“从缓存重新加载”,设置各种响应标头),这里是仅有的两个解决方案我:
1- 简单方法:从 javascript 动态创建 iframe
例如:
const iframe = document.createElement('iframe')
iframe.id = ...
...
iframe.src = myIFrameUrl
document.body.appendChild(iframe)
2- 复杂的方式
服务器端,正如 here 所解释的那样,为您为 iframe或 为父页面提供的内容禁用内容缓存(两者都可以)。
与
从 javascript 中设置 iframe url,并使用额外的更改搜索参数,如下所示:
const url = myIFrameUrl + '?timestamp=' + new Date().getTime()
document.getElementById('my-iframe-id').src = url
(简化版,注意其他搜索参数)
【讨论】:
【参考方案13】:我也遇到了这个问题,在尝试了不同的浏览器和大量的试验和错误之后,我想出了这个解决方案,在我的情况下效果很好:
import defineComponent from 'vue'
import v4 as uuid from 'uuid'
export default defineComponent(
setup()
return () => (
// append a uuid after `?` to prevent browsers from caching it
<iframe src=`https://www.example.com?$uuid()` frameborder='0' />
)
,
)
【讨论】:
以上是关于防止浏览器中的 iframe 缓存的主要内容,如果未能解决你的问题,请参考以下文章