我们的调查表明,并非所有浏览器都以统一的方式尊重HTTP缓存指令。

出于安全原因,我们不希望应用程序中的某些页面被web浏览器缓存。这必须至少适用于以下浏览器:

Internet Explorer 6+Firefox 1.5+Safari 3+歌剧9+铬

我们的要求来自安全测试。从我们的网站注销后,您可以按后退按钮并查看缓存的页面。


当前回答

接受的答案似乎不适用于IIS7+,因为II7中存在大量关于未发送缓存头的问题:

某些事情正在迫使响应具有缓存控制:IIS7中的私有IIS7:缓存设置不工作。。。为什么?IIS7+ASP.NET MVC客户端缓存标头不工作为aspx页面设置缓存控制缓存控制:没有存储,必须重新验证,不能发送到IIS7+ASP.NET MVC中的客户端浏览器

等等

接受的答案是正确的,必须在哪些标题中设置,但不能在如何设置标题中设置。这种方式适用于IIS7:

Response.Cache.SetCacheability(HttpCacheability.NoCache);
Response.Cache.AppendCacheExtension("no-store, must-revalidate");
Response.AppendHeader("Pragma", "no-cache");
Response.AppendHeader("Expires", "-1");

第一行将Cache控件设置为no Cache,第二行添加其他属性no store,must revalidate

其他回答

(嘿,大家:请不要盲目地复制和粘贴所有你能找到的标题)

首先,后退按钮历史记录不是缓存:

新鲜度模型(第4.2节)不一定适用于历史机制。也就是说,历史机制可以显示以前的表示,即使它已经过期。

在旧的HTTP规范中,措辞更加强硬,明确告诉浏览器忽略后退按钮历史的缓存指令。

Back应该返回到时间(用户登录时的时间)。它不会导航到以前打开的URL。

然而,实际上,在非常特殊的情况下,缓存会影响后退按钮:

页面必须通过HTTPS传递,否则,这种缓存破坏将不可靠。此外,如果您没有使用HTTPS,那么您的页面很容易以其他方式被窃取登录信息。您必须发送缓存控制:无存储,必须重新验证(某些浏览器观察到无存储,有些浏览器观察到必须重新验证)

您永远不需要:

<meta>带有缓存头-它根本不起作用。完全没用。后检查/预检查-这是一个仅适用于可计算资源的IE指令。发送相同的标题两次或十几次。一些PHP片段实际上取代了以前的头,导致只发送最后一个。

如果需要,可以添加:

没有缓存或最大年龄=0,这将使资源(URL)“过时”,并要求浏览器与服务器检查是否有更新的版本(没有商店已经暗示了这一点)。对于HTTP/1.0客户端,过期日期为过去的日期(尽管现在真正的HTTP/1.0客户机完全不存在)。


好处:新的HTTP缓存RFC。

//In .net MVC
[OutputCache(NoStore = true, Duration = 0, VaryByParam = "*")]
public ActionResult FareListInfo(long id)
{
}

// In .net webform
<%@ OutputCache NoStore="true" Duration="0" VaryByParam="*" %>

RFC for HTTP 1.1指出,正确的方法是为以下内容添加HTTP标头:

缓存控制:无缓存

如果较旧的浏览器不符合HTTP 1.1,它们可能会忽略这一点。对于那些你可以尝试标题:

Pragma:无缓存

这也适用于HTTP1.1浏览器。

我发现这一页上的所有答案仍然存在问题。特别是,我注意到,当您通过单击后退按钮访问页面时,它们都不会阻止IE8使用缓存版本的页面。

经过大量研究和测试,我发现我真正需要的两个标题是:

缓存控制:无存储变化:*

有关Vary标头的说明,请查看http://www.w3.org/Protocols/rfc2616/rfc2616-sec13.html#sec13.6

在IE6-8、FF1.5-3.5、Chrome 2-3、Safari 4和Opera 9-10上,当您单击页面链接或将URL直接放入地址栏时,这些标题会导致服务器请求页面。截至2010年1月,这涵盖了99%的浏览器。

在IE6和Opera 9-10上,点击后退按钮仍然会加载缓存版本。在我测试的所有其他浏览器上,它们确实从服务器获取了新版本。到目前为止,我还没有找到任何一组标头,当您单击后退按钮时,这些标头会导致这些浏览器无法返回缓存的页面版本。

更新:写下这个答案后,我意识到我们的web服务器正在将自己标识为HTTP 1.0服务器。我列出的标头是正确的,以便浏览器不会缓存来自HTTP 1.0服务器的响应。对于HTTP 1.1服务器,请查看BalusC的答案。

我用这种方式解决了。

2个注意事项:

1) 服务器端事件不是在后退单击时触发的,而是javascript。

2) 我有两个javascript来读/写cookie

function setCookie(name, value, days)
{
    var expires = "";
    if (days)
    {
        var date = new Date();
        date.setTime(date.getTime() + (days * 24 * 60 * 60 * 1000));
        expires = "; expires=" + date.toUTCString();
    }
    document.cookie = name + "=" + (value || "") + expires + "; path=/";
}

function getCookie(name)
{
    var nameEQ = name + "=";
    var ca = document.cookie.split(';');

    for (var i = ca.length - 1; i >= 0; i--)
    {
        var c = ca[i];
        while (c.charAt(0) == ' ')
        {
            c = c.substring(1, c.length);
        }

        if (c.indexOf(nameEQ) == 0)
        {
            return c.substring(nameEQ.length, c.length);
        }
    }
    return null;
}

在我的Page_Load中,我插入了以下内容:(这不是在单击后启动的)

    protected void Page_Load(object sender, EventArgs e)
    {
       Page.RegisterClientScriptBlock("", "<script>setCookie('" + Session.SessionID + "', '" + Login + "', '100');</script>");
    }

其中“Login”是我的id值,注销后为-1(可以使用其他值,例如布尔值)。

然后在我的页面中添加了以下内容:(这是在单击后启动的)

<script type="text/javascript">
if (getCookie('<%= Session.SessionID %>') < 0)
        {
            if (history.length > 0)
            {
                history.go(+1);
            }
        }

</script>

没有别的。

使用此解决方案,仅在同一浏览器上的每个页面注销后,才在每个页面上启用反向单击。