97

如何防止 Firefox 和 Safari 缓存 iframe 内容?

我有一个简单的网页,带有 iframe 到不同网站上的页面。外页和内页都有 HTTP 响应标头以防止缓存。当我在浏览器中单击“返回”按钮时,外部页面可以正常工作,但无论如何,浏览器总是会检索 iframed 页面的缓存。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.

这是我到目前为止所尝试的:

  • 使用随机 var 值更改 iframe URL
  • 将 Expires、Cache-Control 和 Pragma 标头添加到外部网页
  • 将 Expires、Cache-Control 和 Pragma 标头添加到内部网页

我无法使用任何 JavaScript 技巧,因为我被同源策略阻止了。

我的想法不多了。有谁知道如何阻止浏览器缓存 iframed 内容?

更新

我按照 Daniel 的建议安装了 Fiddler2 进行另一次测试,不幸的是,我仍然得到相同的结果。

这是我进行的测试:

  1. Math.random()外页使用JSP生成随机数。
  2. 外页在网页上显示一个随机数。
  3. 外页调用iframe,传入一个随机数。
  4. 内页显示一个随机数。

通过这个测试,我可以准确地看到哪些页面正在更新,哪些页面被缓存了。

视觉测试

为了快速测试,我加载页面,导航到另一个页面,然后按“返回”。结果如下:

原始页面:

  • 外页: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被调用。

好吧,从这个测试来看,Web 浏览器似乎没有缓存页面,但它正在缓存 iframe 的 URL,然后对该缓存的 URL 发出新请求。但是,我仍然对如何解决这个问题感到困惑。

有人对如何阻止网络浏览器缓存 iframe URL 有任何想法吗?

4

13 回答 13

67

这是 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>
于 2010-10-21T03:30:10.733 回答
43

我已经能够通过name在 iframe 上设置一个唯一属性来解决这个错误 - 无论出于何种原因,这似乎破坏了缓存。您可以使用您拥有的任何动态数据作为name属性 - 或者只是使用您正在使用的任何模板语言中的当前 ms 或 ns 时间。这是一个比上面更好的解决方案,因为它不直接需要 JS。

在我的特殊情况下,iframe 是通过 JS 构建的(但你可以通过 PHP、Ruby 等做同样的事情),所以我只需使用Date.now()

return '<iframe src="' + src + '" name="' + Date.now() + '" />';

这修复了我测试中的错误;可能是因为window.name内部窗口中的变化。

于 2014-10-04T08:47:29.330 回答
17

正如你所说,这里的问题不是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- 复杂的方式

如此处所述,服务器端禁用您为 iframe父页面提供的内容的内容缓存(两者都可以)。

使用额外的更改搜索参数从 javascript 设置 iframe url,如下所示:

const url = myIFrameUrl + '?timestamp=' + new Date().getTime()
document.getElementById('my-iframe-id').src = url

(简化版,注意其他搜索参数)

于 2018-09-25T22:06:57.263 回答
5

在尝试了其他所有方法之后(除了对 iframe 内容使用代理),我找到了一种防止 iframe 内容缓存的方法,来自同一个域

使用.htaccess重写规则并更改 iframesrc属性。

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

两者都指向同一页面。

您可以使用以下方式访问隐藏的 url 参数$_SERVER["QUERY_STRING"]

于 2015-04-22T17:41:56.660 回答
4

截至 2016 年 3 月 17 日,我在最新的 Chrome 和 Mac OS X 上的最新 Safari 中发现了这个问题。上述修复均不适合我,包括将 src 分配为空然后返回到某个站点,或添加一些随机命名的“name”参数,或者在 URL 的末尾添加一个随机数,或者在分配 src 之后将内容窗口 href 分配给 src。

就我而言,这是因为我使用 Javascript 来更新 IFRAME,并且只切换 URL 中的哈希值。

在我的情况下,解决方法是我创建了一个临时 URL,该 URL 具有 0 秒元重定向到该其他页面。它发生得如此之快,以至于我几乎没有注意到屏幕闪烁。另外,我将中间页面的背景颜色设置为与其他页面相同,因此您不会注意到它。

于 2016-03-17T19:22:48.187 回答
3

这是 Firefox 3.5 中的一个错误。

看看.. https://bugzilla.mozilla.org/show_bug.cgi?id=279048

于 2011-03-23T06:03:10.263 回答
3

要让 iframe 始终加载新内容,请将当前 Unix 时间戳添加到 GET 参数的末尾。然后浏览器将其视为“不同”请求,并将寻找新内容。

在 Javascript 中,它可能看起来像:

frames['my_iframe'].location.href='load_iframe_content.php?group_ID=' + group_ID + '&timestamp=' + timestamp;
于 2014-05-12T21:36:50.833 回答
2

我稍后在我的应用程序中设置了 iframe src 属性。要在应用程序开始时摆脱 iframe 中的缓存内容,我只需执行以下操作:

myIframe.src = "";

...在 js 代码开头的某个地方(例如在 jquery $() 处理程序中)

感谢 http://www.freshsupercool.com/2008/07/10/firefox-caching-iframe-data/

于 2012-04-18T09:10:48.450 回答
0

我在 2016 年使用 iOS Safari 时也遇到了这个问题。似乎对我有用的是给 iframe src 一个 GET 参数和一个像这样的值

<iframe width="60%" src="../other/url?cachebust=1" allowfullscreen></iframe>

于 2016-08-06T13:16:43.200 回答
0

我也遇到了这个问题,在尝试了不同的浏览器和大量的试验和错误之后,我想出了这个解决方案,在我的情况下效果很好:

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' />
    )
  },
})
于 2021-07-12T08:32:15.453 回答
-1

如果您想变得非常疯狂,您可以将页面名称实现为始终解析为同一页面的动态 url,而不是查询字符串选项?

假设您在办公室,请检查网络级别是否正在进行任何缓存。相信我,这是一种可能。您的 IT 人员将能够告诉您是否有任何围绕 HTTP 缓存的网络基础设施,尽管这仅发生在 iframe 上,这不太可能。

于 2010-10-07T10:43:03.313 回答
-2

你安装了Fiddler2吗?

它可以让您准确地看到请求的内容、发回的内容等。浏览器真的会针对不同的 URL 访问其缓存,这听起来不太合理。

于 2010-04-15T18:43:00.487 回答
-4

使 iframe 的 URL 指向您网站上的页面,该页面充当代理来检索和返回 iframe 的实际内容。现在您不再受同源策略的约束(编辑:不会阻止 iframe 缓存问题)。

于 2010-06-29T16:50:00.417 回答