如何以编程方式清空浏览器缓存?

167

我正在寻找一种程序化清空浏览器缓存的方法。我这样做是因为该应用程序缓存了机密数据,当您按下“注销”时,我希望删除这些数据。这可以通过服务器或JavaScript实现。当然,在外部/公共计算机上使用软件仍然是不鼓励的,因为还有更多的危险,例如键盘记录器,在软件级别上无法打败它们。


3
哪些浏览器?你还应该考虑告诉浏览器从服务器不要缓存什么,而不是试图清除缓存。 - Mech
1
您可能还想查看有关缓存及其工作方式的教程。http://www.mnot.net/cache_docs/ 包括缓存控制头等相关内容。 - scrappedcola
2
@rFactor 没有人会使用那种让网站控制其缓存的浏览器。 - NullUserException
3
实际上,网站对缓存具有控制权,因为它们控制HTTP头。 - Danubian Sailor
@NullUserException:在我看来,这是一个过于牵强附会的说法。大多数普通用户很乐意将网站对Cookies、localStorage等的控制权交给服务器域。因此,如果服务器控制浏览器缓存以服务其域名,大多数普通用户也不会感到惊讶。 - nishanthshanmugham
显示剩余3条评论
14个回答

190
2023年更新:请参见Clear-Site-Data HTTP头,通过该头信息,服务器可以指示客户端Web浏览器清除其域名/子域名的网站缓存,而不考虑之前的Cache-Control头。中间缓存可能仍然具有缓存数据,并且可能不遵守该头信息。(感谢@nishanthshanmugham) 没有办法让浏览器清除其缓存。如果这是可能的,那将是一个巨大的安全问题。这很容易被滥用——一旦浏览器支持这样的“功能”,我就会立即卸载它。
您可以通过发送适当的头信息或使用这些元标记来告诉浏览器不要缓存您的页面。
<meta http-equiv='cache-control' content='no-cache'>
<meta http-equiv='expires' content='0'>
<meta http-equiv='pragma' content='no-cache'>

您可能还想考虑关闭表单字段的自动完成功能,尽管我恐怕没有标准方法来实现它( 参见此问题)。

无论如何,我想指出,如果您正在处理敏感数据,应该使用 SSL。如果您没有使用 SSL,任何可以访问网络的人都可以嗅探网络流量,并轻松地看到用户所看到的内容。

使用 SSL 还会使一些浏览器使用缓存,除非明确告知。请参阅 此问题


9
我为什么要清除我的Web应用程序缓存以打扰我的用户?我这样做是为了清除缓存的私人数据痕迹。如果我告诉浏览器不要缓存,它每次加载页面时都必须请求几兆字节的客户端数据,这也不是我想要的。 - Tower
33
显然没有人会这样做,因为这是不可能的。就像你不能在另一个来源上运行脚本一样,并不意味着你不能在你的来源上运行脚本。如果你无法清除远程来源的缓存,那很正常,但为什么我不能清除我执行代码所在来源的缓存呢?没有理由不行,所以我正在寻找解决办法,但看起来这是不可能的。如果你有兴趣,我可以告诉你,我有一个大型应用程序,其中包含大量编译为约6 MB的CSS、HTML和JS。 - Tower
4
@rFactor 这太多了。 - NullUserException
21
请解释无论如何实现,这都会是一个安全问题的原因?实现可以安全进行。无论采用何种方式实现,都可能存在安全问题。然而,如果谨慎地实施,该实现也可以安全进行。 - Dan
33
也许我昨晚没睡够,如果一个 Web 应用程序可以清除(而不是更改)缓存,会以哪些方式成为安全问题?你如何利用它? - Volker E.
显示剩余10条评论

43

这是可能的,你可以简单地使用jQuery来替换引用缓存状态的“meta标签”为事件处理程序/按钮,然后刷新,很容易。

$('.button').click(function() {
    $.ajax({
        url: "",
        context: document.body,
        success: function(s,x){

            $('html[manifest=saveappoffline.appcache]').attr('content', '');
                $(this).html(s);
        }
    }); 
});

注意:此解决方案依赖于作为 HTML 5 规范的一部分实现的应用程序缓存。它还需要服务器配置来设置 App Cache 清单。它不描述通过客户端或服务器端代码清除“传统”浏览器缓存的方法,这几乎是不可能的。


这只是HTML5的特性吗? - John Naegle
我认为是这样,并且我相信它还需要服务器配置(来设置应用程序缓存清单)。虽然这个答案提供了原问题的解决方案,但它掩盖了一个事实,即通过客户端或服务器端代码清除传统浏览器缓存几乎是不可能的。 - Eric Fuller
这种方法似乎可以绕过缓存并更新内容,但是当页面重新加载时,它会回到先前缓存的内容。 - Simpler
已被服务工作者取代,详情请参考 https://developer.mozilla.org/zh-CN/docs/Web/API/Service_Worker_API/Using_Service_Workers - nadav
2
服务工作者在iPhone上无法使用,因此您必须在那里使用应用程序缓存。 - tony

29

可以使用HTML本身一个小技巧来解决这个问题,即向脚本标签的文件名附加一个参数/字符串,并在文件更新时更改它。

<script src="myfile.js?version=1.0.0"></script>

浏览器将整个字符串都解释为文件路径,即使 "?" 后面是参数。因此,下一次更新文件时,只需更改网站上脚本标签中的数字(例如 <script src="myfile.js?version=1.0.1"></script>),每个用户的浏览器都会看到文件已经更改,并获取新的副本。


1
对于那些使用服务器端动态语言的人,如果您可以访问文件的 ctime(或 mtime),您只需在其后添加该时间即可。例如,在 PHP 中,myfile.js?v=<?=filectime('myfile.js');?>,这样您就可以为资源创建一个自动更新的缓存。 - Pierre-Antoine Guillaume
我使用这种技术已经很多天了。但是今天我注意到,即使我更改了版本部分,文件仍然从缓存中呈现。我使用的是Chrome浏览器。即使我从服务器上删除了该文件,它仍然显示在浏览器中。有人知道为什么会出现这种情况吗? - Tᴀʀᴇǫ Mᴀʜᴍᴏᴏᴅ
这个技巧很有效,https://dev59.com/6XI-5IYBdhLWcg3wTWZu - Nevin
这是我自2002年以来一直使用的方法。它可能很丑陋,但它总是有效的。如果没有全新的HTML 5.0功能,我认为这是唯一能够同时缓存页面并选择何时获取新副本(即:清除缓存)的方法。 - ebyrob
这种技术强制执行GET请求并从浏览器缓存的角度查询文件,但它不会使仍在缓存中的旧文件失效。每当您使用相同查询(并且浏览器已被指示进行缓存)再次进行先前完成的请求时,您将从缓存中获取此文件。添加n个新查询会填充n个缓存条目。如果不小心添加随机查询,则会快速污染浏览器缓存->然后是缓存崩溃。 - Leo

9
最好的做法是使用名称+版本哈希值生成JS文件,如果需要清除缓存,只需生成新的带有新哈希值的文件,这将触发浏览器加载新文件。

9
这里是一行简单的代码,使用Cache.delete()方法可以删除所有浏览器网络缓存。
caches.keys().then((keyList) => Promise.all(keyList.map((key) => caches.delete(key))))

支持Chrome 40+,Firefox 39+,Opera 27+和Edge浏览器。


15
这个只针对那些被脚本(通常是在服务工作者中)使用缓存API明确存储的物品。它不会让你访问浏览器的HTTP(s)缓存。 - Tamlyn

8
你可以让服务器响应一个清除站点数据指令,指示用户代理清除站点的本地存储数据。
例如:
Clear-Site-Data: "cache", "cookies", "storage"

该标头将指示用户代理清除所有本地存储的数据,包括:
  • 网络缓存
  • 用户代理缓存(如预渲染页面、脚本缓存等)
  • Cookies
  • HTTP身份验证凭据
  • 原始绑定令牌(例如通道ID和令牌绑定)
  • 本地存储
  • 会话存储
  • IndexedDB
  • Web SQL数据库
  • Service Worker注册
您可以使用fetch()发送请求,然后执行location.reload()以获取全新的重启。

1
这在Safari中不受支持,Firefox在63版本中添加了对其的支持,但在94版本中删除了对其的支持。 - Grintor

7
在Chrome浏览器中,您可以使用基准测试扩展来完成此操作。您需要使用以下开关启动Chrome:
./chrome --enable-benchmarking --enable-net-benchmarking 

现在在Chrome的控制台中,您可以执行以下操作:
chrome.benchmarking.clearCache();
chrome.benchmarking.clearHostResolverCache();
chrome.benchmarking.clearPredictorCache();
chrome.benchmarking.closeConnections();

从上述命令中可以看出,它不仅清除浏览器缓存,还清除DNS缓存并关闭网络连接。当您进行页面加载时间基准测试时,这些功能非常实用。如果只需要清除缓存而不关心DNS缓存和连接,则只需使用clearCache()即可,无需全部使用。


7

起初,我尝试用各种编程方法在html、JS中清除浏览器缓存,但最新版本的Chrome上都没用。

最终,我使用了.htaccess:

<IfModule mod_headers.c>
    Header set Cache-Control "no-cache, no-store, must-revalidate"
    Header set Pragma "no-cache"
    Header set Expires 0
</IfModule>

已在Chrome、Firefox和Opera中测试

参考:https://wp-mix.com/disable-caching-htaccess/


1
这是最好的修复。 - The Naga Tanker
它也是最慢的修复方法,需要使用 Apache Web 服务器,但总的来说我认为现在它已经不太好了。 - france1

5

使用location.reload(true);将会强制重新加载当前页面,忽略缓存。
Cache.delete()也可以在新版Chrome、Firefox和Opera中使用。


此函数不支持Internet Explorer和Safari浏览器。不确定是否适用于Microsoft Edge。 - Curious Developer
听起来这可能是一种仅适用于Firefox的怪癖。 - Robotnik

5

现在你可以使用Cache.delete()函数。

例如:

let id = "your-cache-id";
// you can find the id by going to 
// application>storage>cache storage 
// (minus the page url at the end)
// in your chrome developer console 

caches.open(id)
.then(cache => cache.keys()
  .then(keys => {
    for (let key of keys) {
      cache.delete(key)
    }
  }));

适用于Chrome 40+,Firefox 39+,Opera 27+和Edge。


2
最佳答案。完美运作。 - YTG

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接