【问题标题】:How to prevent browser page caching in Rails如何防止 Rails 中的浏览器页面缓存
【发布时间】:2010-10-17 05:17:20
【问题描述】:

Ubuntu -> Apache -> Phusion Passenger -> Rails 2.3

我网站的主要部分会对您的点击做出反应。因此,如果您单击一个链接,它会将您发送到目的地,并立即重新生成您的页面。

但是,如果您点击后退按钮,您将看不到新页面。不幸的是,如果没有手动刷新,它就不会出现;看来浏览器正在缓存它。我想确保浏览器不缓存页面。

另外,我确实想为我的所有静态资产设置遥远的到期日期。

解决这个问题的最佳方法是什么?我应该在 Rails 中解决这个问题吗?阿帕奇? Javascript?

感谢您的所有帮助, 杰森


唉。这些建议都没有强迫我正在寻找的行为。

也许有一个 javascript 答案?我可以让 rails 在评论中写出时间戳,然后让 javascript 检查时间是否在五秒内(或任何有效的时间)。如果是,那很好,但如果不是,那么重新加载页面?

你认为这行得通吗?

感谢您的帮助,

杰森

【问题讨论】:

    标签: ruby-on-rails ruby apache caching http-headers


    【解决方案1】:

    终于想通了 - http://blog.serendeputy.com/posts/how-to-prevent-browsers-from-caching-a-page-in-rails/ in application_controller.rb

    Rails 5 之后:

    class ApplicationController < ActionController::Base
    
      before_action :set_cache_headers
    
      private
    
      def set_cache_headers
        response.headers["Cache-Control"] = "no-cache, no-store"
        response.headers["Pragma"] = "no-cache"
        response.headers["Expires"] = "Mon, 01 Jan 1990 00:00:00 GMT"
      end
    end
    

    Rails 4 及更早版本:

    class ApplicationController < ActionController::Base
    
      before_filter :set_cache_headers
    
      private
    
      def set_cache_headers
        response.headers["Cache-Control"] = "no-cache, no-store"
        response.headers["Pragma"] = "no-cache"
        response.headers["Expires"] = "Mon, 01 Jan 1990 00:00:00 GMT"
      end
    end
    

    【讨论】:

    • 是否应该将其包裹在“if request.xhr”中?所以它只会在 ajax 刷新时设置,而普通页面不会?
    • 只要浏览器兼容 HTTP 1.1,你只需要Cache-Control: no-storeSection 14.9.2 What May be Stored by Caches
    • 1990 年 1 月 1 日是星期一!
    • 它对我不起作用我在 application_controller.rb 中添加了相同的代码,注销后我可以通过后退按钮看到最后一页。请指导我哪里错了?
    • 这是否也不会在 rails 应用程序中缓存 JS 和 CSS?每个请求都会从服务器加载 JS 和 CSS 吗?
    【解决方案2】:

    no_cache_control Gem.

    如果您需要对所有响应执行此操作,例如要通过渗透测试(BURP、Detectify 等),您可以安装此 Gem on Rails 4+,以便将以下标头添加到所有响应中:

    Cache-Control: no-cache, no-store, max-age=0, must-revalidate
    Pragma: no-cache
    Expires: -1
    

    就像一个魅力,对于需要身份验证才能执行任何操作的安全 HTTPS Web 应用程序来说,它确实是正确的方法。

    【讨论】:

      【解决方案3】:

      注意点:您不能有条件地清除缓存(例如,如果 before_filter 仅在用户已经到过该位置时才调用 reset_cache)。您需要无条件地清除缓存,因为浏览器不会发出新的请求,只是为了看看这次是否需要重新加载,即使上次不需要。 p>

      例子:

      before_filter :reset_cache, if: :user_completed_demographics?
      

      无法阻止用户在访问后返回,因为浏览器使用“后退”按钮上的原始缓存标头。

      before_filter :reset_cache
      

      但是会起作用(显然,在刷新页面并清除添加之前的缓存之后),因为在第一次请求时,浏览器将获得 no-cache, no-store, ... 并将其应用于未来的页面加载。

      【讨论】:

        【解决方案4】:

        【讨论】:

        • expires_now 仅发送 no-cache 标头。根据浏览器,这可能还不够。 (例如 Firefox 想要一个 no-store 用于非 HTTPS 连接:developer.mozilla.org/en/docs/Using_Firefox_1.5_caching
        • 同意,这不是一个有效的解决方案,用 Rails 5.2 和 Chrome 77 测试过。还需要no-store
        【解决方案5】:

        更简洁的方法是编写一个 Rack 中间件,它根据某些逻辑更改 Cache-Control 标头(例如,仅适用于 application/xml mime-type)。 或者,对于一种更丑陋但仍然有效的方法,可以将 ActionDispatch::Response::DEFAULT_CACHE_CONTROL 常量更改为“无缓存”。 当然,如果需要控制器和/或动作粒度,那么最好在控制器中执行此操作。

        【讨论】:

          【解决方案6】:

          我在控制器中使用了这条线并取得了一些成功。它适用于 Safari 和 Internet Explorer,但我还没有看到它适用于 Firefox。

          response.headers["Expires"] = "#{1.year.ago}"
          

          对于您的第二点,如果您使用 rails 辅助方法,例如

          stylesheet_link_tag
          

          并在您的网络服务器上保留默认设置,资产通常会被很好地缓存。

          【讨论】:

          • 1.year.ago 是不必要的开销。只需选择过去的任意时间,例如Fri, 01 Jan 1990 00:00:00 GMT
          • @Archonic 1990 年 1 月 1 日是星期一!
          猜你喜欢
          • 1970-01-01
          • 2012-06-19
          • 2010-10-25
          • 1970-01-01
          • 1970-01-01
          • 2020-11-03
          • 2023-03-21
          • 1970-01-01
          • 1970-01-01
          相关资源
          最近更新 更多