Cách ngăn bộ đệm trang trình duyệt trong Rails


151

Ubuntu -> Apache -> Hành khách lừa đảo -> Rails 2.3

Phần chính của trang web của tôi phản ứng với các nhấp chuột của bạn. Vì vậy, nếu bạn nhấp vào một liên kết, nó sẽ đưa bạn đến đích và ngay lập tức tạo lại trang của bạn.

Nhưng, nếu bạn nhấn nút quay lại, bạn sẽ không thấy trang mới. Thật không may, nó không hiển thị mà không làm mới thủ công; Nó xuất hiện trình duyệt đang lưu trữ nó. Tôi muốn đảm bảo trình duyệt không lưu trữ trang.

Riêng, tôi làm muốn thiết lập ngày hết hạn xa trong tương lai cho toàn bộ tài sản tĩnh của tôi.

Cách tốt nhất để giải quyết điều này là gì? Tôi có nên giải quyết điều này trong Rails? Apache? Javascript?

Cảm ơn tất cả sự giúp đỡ của bạn, Jason


Than ôi. Cả hai gợi ý này đều buộc hành vi tôi đang tìm kiếm.

Có lẽ có một câu trả lời javascript? Tôi có thể yêu cầu viết một dấu thời gian trong một bình luận, sau đó kiểm tra javascript để xem thời gian có trong vòng năm giây không (hoặc bất cứ điều gì hoạt động). Nếu có, thì tốt, nhưng nếu không, sau đó tải lại trang?

Bạn có nghĩ rằng điều này sẽ làm việc?

Cảm ơn tất cả sự giúp đỡ của bạn,

Jason

Câu trả lời:


335

Cuối cùng đã tìm ra điều này - http://blog.serendeputy.com/posts/how-to-prevent-browsers-from-caching-a-page-in-rails/ inapplication_controller.rb

Sau đường ray 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 và phiên bản cũ hơn:

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

3
Điều này có nên được gói trong một "nếu request.xhr?" Vì vậy, nó chỉ được thiết lập trên ajax làm mới nhưng các trang bình thường thì không?
MintDeparture

3
Bạn chỉ thực sự cần Cache-Control: no-storemiễn là trình duyệt tuân thủ HTTP 1.1. Mục 14.9.2 Những gì có thể được lưu trữ bởi Caches
gaqzi

28
Ngày 1 tháng 1 năm 1990, là một ngày thứ Hai!
Jan Hettich

2
Nó không hoạt động đối với tôi Tôi đã thêm cùng một mã trong application_controll.rb và sau khi đăng xuất tôi có thể thấy trang cuối cùng bằng nút quay lại. Xin hướng dẫn cho tôi biết tôi sai ở đâu?
Thorin

1
Điều này cũng KHÔNG lưu cache JS và CSS trong ứng dụng rails? JS và CSS sẽ được tải từ máy chủ cho mỗi yêu cầu?
furiabhavesh

14

3
expires_nowchỉ gửi no-cachetiêu đề. Tùy thuộc vào trình duyệt này có thể không đủ. (Ví dụ: Firefox muốn có no-storecác kết nối không phải HTTPS: developer.mozilla.org/en/docs/Using_Firefox_1.5_caching )
Daniel Rikowski

1
Đồng ý, đây không phải là một giải pháp hợp lệ, được thử nghiệm với Rails 5.2 và Chrome 77. no-storecũng cần thiết.
AndrewSouthpaw

3

Tôi đã sử dụng dòng này với một số thành công trong bộ điều khiển. Nó hoạt động trong Safari và Internet Explorer nhưng tôi chưa thấy nó hoạt động với Firefox.

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

Đối với điểm thứ hai của bạn, nếu bạn sử dụng các phương thức của trình trợ giúp đường ray như

stylesheet_link_tag

và để lại các thiết lập mặc định trên máy chủ web của bạn, các tài sản thường được lưu trữ khá tốt.


3
1.year.agolà chi phí không cần thiết. Chỉ cần chọn một số thời gian tùy ý trong quá khứ nhưFri, 01 Jan 1990 00:00:00 GMT
Archonic

6
@Archonic 1 tháng 1 năm 1990 là thứ hai!
Thomas R. Koll

1

Cách sạch hơn sẽ là viết một phần mềm trung gian Rack, thay đổi tiêu đề Cache-Control dựa trên một số logic (ví dụ: chỉ dành cho loại mime ứng dụng / xml). Hoặc, đối với cách tiếp cận xấu hơn nhưng vẫn hoạt động, người ta có thể thay đổi hằng số ActionDispatch :: Feedback :: DEFAULT_CACHE_CONTROL thành 'no-cache'. Tất nhiên, nếu bộ điều khiển và / hoặc độ chi tiết hành động là bắt buộc, thì tốt hơn là làm điều này trong bộ điều khiển.


1

Điểm lưu ý: Bạn không thể xóa bộ nhớ cache một cách before_filtercó điều kiện (như nếu chỉ một cuộc gọi reset_cachenếu người dùng đã ở đó). Bạn cần xóa bộ nhớ cache một cách vô điều kiện , bởi vì trình duyệt sẽ không đưa ra yêu cầu mới chỉ để xem liệu lần này, nó có cần tải lại hay không, mặc dù không cần phải kéo dài.

Thí dụ:

before_filter :reset_cache, if: :user_completed_demographics?

sẽ không hoạt động để ngăn người dùng quay lại sau khi họ đã ở đó, vì trình duyệt sử dụng các tiêu đề bộ đệm ban đầu trên nút Quay lại.

before_filter :reset_cache

Tuy nhiên, sẽ hoạt động (sau khi làm mới trang và xóa bộ đệm từ trước khi bạn thêm điều này, rõ ràng), vì, trong yêu cầu đầu tiên, trình duyệt sẽ nhận no-cache, no-store, ...và áp dụng nó cho tải trang trong tương lai.


0

no_cache_control Đá quý.

Nếu bạn cần thực hiện điều này cho tất cả các phản hồi, ví dụ: để vượt qua bài kiểm tra thâm nhập (BURP, Detectify, v.v.), bạn có thể cài đặt Gem này trên Rails 4+ để thêm các tiêu đề sau vào tất cả các phản hồi:

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

Hoạt động như một cơ duyên và thực sự là cách phù hợp để sử dụng các ứng dụng web HTTPS an toàn, yêu cầu xác thực để làm bất cứ điều gì.

Khi sử dụng trang web của chúng tôi, bạn xác nhận rằng bạn đã đọc và hiểu Chính sách cookieChính sách bảo mật của chúng tôi.
Licensed under cc by-sa 3.0 with attribution required.