etc./StackOverFlow

모든 브라우저에서 웹 페이지 캐싱을 어떻게 제어합니까?

청렴결백한 만능 재주꾼 2022. 1. 5. 09:43
반응형

질문자 :Edward Wilde


조사 결과 모든 브라우저가 동일한 방식으로 HTTP 캐시 지시문을 준수하는 것은 아닙니다.

보안상의 이유로 우리는 우리의 응용 프로그램에서 특정 페이지가 웹 브라우저에 의해, 지금까지, 캐시 싶지 않아요. 이것은 최소한 다음 브라우저에서 작동해야 합니다.

  • 인터넷 익스플로러 6+
  • 파이어폭스 1.5+
  • 사파리 3+
  • 오페라 9+
  • 크롬

우리의 요구 사항은 보안 테스트에서 나왔습니다. 당사 웹사이트에서 로그아웃한 후 뒤로 버튼을 눌러 캐시된 페이지를 볼 수 있습니다.



소개

언급된 모든 클라이언트(및 프록시)에서 작동하는 올바른 최소 헤더 세트:

 Cache-Control: no-cache, no-store, must-revalidate Pragma: no-cache Expires: 0

Cache-Control 은 클라이언트 및 프록시에 대한 HTTP 1.1 사양에 따릅니다(그리고 Expires 옆에 있는 일부 클라이언트에서 암시적으로 필요함). Pragma 는 선사 시대 클라이언트에 대한 HTTP 1.0 사양에 따릅니다. Expires 는 클라이언트 및 프록시에 대한 HTTP 1.0 및 1.1 사양에 따릅니다. HTTP 1.1에서 Cache-Control Expires 보다 우선하므로 결국 HTTP 1.0 프록시에만 해당됩니다.

no-store 만 있는 HTTPS를 통해 페이지를 제공할 때 IE6 및 깨진 캐싱에 대해 신경 쓰지 않는다면 Cache-Control: no-cache 생략할 수 있습니다.

 Cache-Control: no-store, must-revalidate Pragma: no-cache Expires: 0

IE6이나 HTTP 1.0 클라이언트(HTTP 1.1은 1997년에 도입됨)에 관심이 없다면 Pragma 생략할 수 있습니다.

 Cache-Control: no-store, must-revalidate Expires: 0

HTTP 1.0 프록시도 신경 쓰지 않는다면 Expires 생략할 수 있습니다.

 Cache-Control: no-store, must-revalidate

반면에 서버가 유효한 Date 헤더를 Cache-ControlExpires 에만 의존할 수 있습니다.

 Date: Wed, 24 Aug 2016 18:32:02 GMT Expires: 0

그러나 예를 들어 최종 사용자가 운영 체제 날짜를 조작하고 클라이언트 소프트웨어가 이에 의존하는 경우 실패할 수 있습니다.

Cache-Control 매개변수가 지정된 max-age 와 같은 기타 Cache-Control 매개변수는 관련이 없습니다. 여기에 있는 대부분의 다른 답변에 포함 Last-Modified 헤더는 실제로 요청을 캐시하려는 경우에만 흥미롭기 때문에 전혀 지정할 필요가 없습니다.

그것을 설정하는 방법?

PHP 사용:

 header("Cache-Control: no-cache, no-store, must-revalidate"); // HTTP 1.1. header("Pragma: no-cache"); // HTTP 1.0. header("Expires: 0"); // Proxies.

Java 서블릿 또는 Node.js 사용:

 response.setHeader("Cache-Control", "no-cache, no-store, must-revalidate"); // HTTP 1.1. response.setHeader("Pragma", "no-cache"); // HTTP 1.0. response.setHeader("Expires", "0"); // Proxies.

ASP.NET-MVC 사용

 Response.Cache.SetCacheability(HttpCacheability.NoCache); // HTTP 1.1. Response.Cache.AppendCacheExtension("no-store, must-revalidate"); Response.AppendHeader("Pragma", "no-cache"); // HTTP 1.0. Response.AppendHeader("Expires", "0"); // Proxies.

ASP.NET 웹 API 사용:

 // `response` is an instance of System.Net.Http.HttpResponseMessage response.Headers.CacheControl = new CacheControlHeaderValue { NoCache = true, NoStore = true, MustRevalidate = true }; response.Headers.Pragma.ParseAdd("no-cache"); // We can't use `response.Content.Headers.Expires` directly // since it allows only `DateTimeOffset?` values. response.Content?.Headers.TryAddWithoutValidation("Expires", 0.ToString());

ASP.NET 사용:

 Response.AppendHeader("Cache-Control", "no-cache, no-store, must-revalidate"); // HTTP 1.1. Response.AppendHeader("Pragma", "no-cache"); // HTTP 1.0. Response.AppendHeader("Expires", "0"); // Proxies.

ASP.NET Core v3 사용

 // using Microsoft.Net.Http.Headers Response.Headers[HeaderNames.CacheControl] = "no-cache, no-store, must-revalidate"; Response.Headers[HeaderNames.Expires] = "0"; Response.Headers[HeaderNames.Pragma] = "no-cache";

ASP 사용:

 Response.addHeader "Cache-Control", "no-cache, no-store, must-revalidate" ' HTTP 1.1. Response.addHeader "Pragma", "no-cache" ' HTTP 1.0. Response.addHeader "Expires", "0" ' Proxies.

Ruby on Rails 사용:

 headers["Cache-Control"] = "no-cache, no-store, must-revalidate" # HTTP 1.1. headers["Pragma"] = "no-cache" # HTTP 1.0. headers["Expires"] = "0" # Proxies.

파이썬/플라스크 사용:

 response = make_response(render_template(...)) response.headers["Cache-Control"] = "no-cache, no-store, must-revalidate" # HTTP 1.1. response.headers["Pragma"] = "no-cache" # HTTP 1.0. response.headers["Expires"] = "0" # Proxies.

Python/Django 사용:

 response["Cache-Control"] = "no-cache, no-store, must-revalidate" # HTTP 1.1. response["Pragma"] = "no-cache" # HTTP 1.0. response["Expires"] = "0" # Proxies.

파이썬/피라미드 사용:

 request.response.headerlist.extend( ( ('Cache-Control', 'no-cache, no-store, must-revalidate'), ('Pragma', 'no-cache'), ('Expires', '0') ) )

이동 사용:

 responseWriter.Header().Set("Cache-Control", "no-cache, no-store, must-revalidate") // HTTP 1.1. responseWriter.Header().Set("Pragma", "no-cache") // HTTP 1.0. responseWriter.Header().Set("Expires", "0") // Proxies.

Clojure 사용(Ring utils 필요):

 (require '[ring.util.response :as r]) (-> response (r/header "Cache-Control" "no-cache, no-store, must-revalidate") (r/header "Pragma" "no-cache") (r/header "Expires" 0))

Apache .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>

HTML 사용:

 <meta http-equiv="Cache-Control" content="no-cache, no-store, must-revalidate"> <meta http-equiv="Pragma" content="no-cache"> <meta http-equiv="Expires" content="0">

HTML 메타 태그 대 HTTP 응답 헤더

아는 것이 중요합니다는 HTML 페이지는 HTTP 연결을 통해 제공하고, 때 헤더는 HTTP 응답 헤더와 HTML 모두에 존재한다는 것이다 <meta http-equiv> 태그, 다음 HTTP 응답 헤더에 지정된 얻을 것이다 우선 순위 HTML 메타 태그 위에 있습니다. file:// URL을 통해 로컬 디스크 파일 시스템에서 페이지를 볼 때만 사용됩니다. W3 HTML 사양 챕터 5.2.2 도 참조하십시오. 웹 서버가 일부 기본값을 포함할 수 있기 때문에 프로그래밍 방식으로 지정하지 않을 때 이 점에 주의하십시오.

일반적으로 초보자의 혼동을 피하고 하드 HTTP 응답 헤더에 의존하려면 HTML 메타 태그를 지정 하지 않는 것이 좋습니다. 더욱이, 특히 이러한 <meta http-equiv> 태그는 HTML5에서 유효하지 않습니다. HTML5 사양에 나열된 http-equiv 값만 허용됩니다.

실제 HTTP 응답 헤더 확인

둘 중 하나를 확인하려면 웹 브라우저 개발자 도구 집합의 HTTP 트래픽 모니터에서 확인/디버그할 수 있습니다. Chrome/Firefox23+/IE9+에서 F12 키를 누른 다음 "네트워크" 또는 "Net" 탭 패널을 연 다음 관심 있는 HTTP 요청을 클릭하여 HTTP 요청 및 응답에 대한 모든 세부 정보를 확인하면 됩니다. 아래 스크린샷 은 Chrome에서 가져온 것입니다.

stackoverflow.com에서 HTTP 응답 헤더를 표시하는 Chrome 개발자 도구 집합 HTTP 트래픽 모니터

파일 다운로드에서도 해당 헤더를 설정하고 싶습니다.

우선, 이 질문과 답변은 "파일 다운로드"(PDF, zip, Excel 등)가 아닌 "웹 페이지"(HTML 페이지)를 대상으로 합니다. 캐시에 저장하고 URI 경로 또는 쿼리 문자열의 어딘가에 파일 버전 식별자를 사용하여 변경된 파일을 강제로 다시 다운로드하는 것이 좋습니다. 어쨌든 파일 다운로드에 캐시가 없는 헤더를 적용할 때 HTTP 대신 HTTPS를 통해 파일 다운로드를 제공할 때 IE7/8 버그에 주의하십시오. 자세한 내용은 IE에서 foo.jsf를 다운로드할 수 없음을 참조하세요. IE는 이 인터넷 사이트를 열 수 없습니다. 요청한 사이트를 사용할 수 없거나 찾을 수 없습니다 .


Community Wiki

(헤이, 여러분: 찾을 수 있는 모든 헤더를 아무 생각 없이 복사하여 붙여넣지 마십시오.)

우선 뒤로 버튼 기록은 캐시 가 아닙니다.

신선도 모델(섹션 4.2)은 반드시 히스토리 메커니즘에 적용되는 것은 아닙니다. 즉, 기록 메커니즘은 만료된 경우에도 이전 표현을 표시할 수 있습니다.

이전 HTTP 사양에서는 더 강력하여 브라우저에 뒤로 버튼 기록에 대한 캐시 지시문을 무시하도록 명시적으로 지시했습니다.

뒤로는 시간을 거슬러 올라가야 합니다(사용자 로그인한 시간으로). 이전에 열린 URL로 앞으로 이동하지 않습니다.

그러나 실제로 캐시는 매우 특정한 상황에서 뒤로 버튼에 영향을 줄 수 있습니다.

  • 페이지 는 HTTPS를 통해 전달 되어야 합니다 . 그렇지 않으면 이 캐시 무효화를 신뢰할 수 없습니다. 또한 HTTPS를 사용하지 않는 경우 페이지는 다른 여러 방식으로 로그인 도용에 취약합니다.
  • Cache-Control: no-store, must-revalidate (일부 브라우저 no-store 를 관찰하고 일부 must-revalidate 관찰함).

다음 중 어느 것도 필요하지 않습니다.

  • <meta> — 전혀 작동하지 않습니다. 전혀 쓸모가 없습니다.
  • post-check / pre-check — 캐시 가능한 리소스에만 적용되는 IE 전용 지시문입니다.
  • 동일한 헤더를 두 번 또는 수십 부분으로 보냅니다. 일부 PHP 스니펫은 실제로 이전 헤더를 대체하므로 마지막 헤더만 전송됩니다.

원하는 경우 다음을 추가할 수 있습니다.

  • no-cache 또는 max-age=0 , 리소스(URL)를 "부실"로 만들고 브라우저에서 최신 버전이 있는지 서버에 확인해야 합니다( no-store 이미 이를 훨씬 더 강력함을 의미함).
  • HTTP/1.0 클라이언트의 경우 과거 날짜로 Expires 됩니다(요즘에는 실제 HTTP/1.0 전용 클라이언트가 완전히 존재하지 않지만).

보너스: 새로운 HTTP 캐싱 RFC .


Kornel

@Kornel이 말했듯이 원하는 것은 캐시를 비활성화하는 것이 아니라 히스토리 버퍼를 비활성화하는 것입니다. 브라우저마다 히스토리 버퍼를 비활성화하는 미묘한 방법이 있습니다.

Cache-Control: no-store 통해서만 이 작업을 수행할 수 있습니다.

FireFox(v23.0.1)에서는 다음 중 하나가 작동합니다.

  1. Cache-Control: no-store

  2. Cache-Control: no-cache (https 전용)

  3. Pragma: no-cache (https 전용)

  4. Vary: * (https만 해당)

Cache-Control: must-revalidate (https만 해당)를 통해서만 이 작업을 수행할 수 있습니다.

Safari(v5.1.7, 7534.57.2)에서는 다음 중 하나가 작동합니다.

  1. Cache-Control: no-store
    HTML의 <body onunload="">

  2. Cache-Control: no-store (https만 해당)

IE8(v8.0.6001.18702IC)에서는 다음 중 하나가 작동합니다.

  1. Cache-Control: must-revalidate, max-age=0

  2. Cache-Control: no-cache

  3. Cache-Control: no-store

  4. Cache-Control: must-revalidate
    Expires: 0

  5. Cache-Control: must-revalidate
    Expires: Sat, 12 Oct 1991 05:00:00 GMT

  6. Pragma: no-cache (https 전용)

  7. Vary: * (https만 해당)

위의 사항을 결합하면 Chrome 28, FireFox 23, IE8, Safari 5.1.7 및 Opera 12.15에서 작동하는 이 솔루션이 제공됩니다. Cache-Control: no-store, must-revalidate (https만 해당)

Opera는 일반 http 페이지에 대한 기록 버퍼를 비활성화하지 않기 때문에 https가 필요합니다. 정말 https를 얻을 수 없고 Opera를 무시할 준비가 되어 있다면 다음과 같이 할 수 있습니다.

 Cache-Control: no-store <body onunload="">

아래는 내 테스트의 원시 로그를 보여줍니다.

HTTP:

  1. Cache-Control: private, no-cache, no-store, must-revalidate, max-age=0, proxy-revalidate, s-maxage=0
    Expires: 0
    Pragma: no-cache
    Vary: *
    <body onunload="">
    실패: 오페라 12.15
    성공: 크롬 28, 파이어폭스 23, IE8, 사파리 5.1.7

  2. Cache-Control: private, no-cache, no-store, must-revalidate, max-age=0, proxy-revalidate, s-maxage=0
    Expires: Sat, 12 Oct 1991 05:00:00 GMT
    Pragma: no-cache
    Vary: *
    <body onunload="">
    실패: 오페라 12.15
    성공: 크롬 28, 파이어폭스 23, IE8, 사파리 5.1.7

  3. Cache-Control: private, no-cache, no-store, must-revalidate, max-age=0, proxy-revalidate, s-maxage=0
    Expires: 0
    Pragma: no-cache
    Vary: *
    실패: 사파리 5.1.7, 오페라 12.15
    성공: 크롬 28, 파이어폭스 23, IE8

  4. Cache-Control: private, no-cache, no-store, must-revalidate, max-age=0, proxy-revalidate, s-maxage=0
    Expires: Sat, 12 Oct 1991 05:00:00 GMT
    Pragma: no-cache
    Vary: *
    실패: 사파리 5.1.7, 오페라 12.15
    성공: 크롬 28, 파이어폭스 23, IE8

  5. Cache-Control: private, no-cache, must-revalidate, max-age=0, proxy-revalidate, s-maxage=0
    Expires: 0
    Pragma: no-cache
    Vary: *
    <body onunload="">
    실패: 크롬 28, 파이어폭스 23, 사파리 5.1.7, 오페라 12.15
    성공: IE8

  6. Cache-Control: private, no-cache, must-revalidate, max-age=0, proxy-revalidate, s-maxage=0
    Expires: Sat, 12 Oct 1991 05:00:00 GMT
    Pragma: no-cache
    Vary: *
    <body onunload="">
    실패: 크롬 28, 파이어폭스 23, 사파리 5.1.7, 오페라 12.15
    성공: IE8

  7. Cache-Control: private, no-cache, must-revalidate, max-age=0, proxy-revalidate, s-maxage=0
    Expires: 0
    Pragma: no-cache
    Vary: *
    <body onunload="">
    실패: 크롬 28, 파이어폭스 23, 사파리 5.1.7, 오페라 12.15
    성공: IE8

  8. Cache-Control: private, no-cache, must-revalidate, max-age=0, proxy-revalidate, s-maxage=0
    Expires: Sat, 12 Oct 1991 05:00:00 GMT
    Pragma: no-cache
    Vary: *
    <body onunload="">
    실패: 크롬 28, 파이어폭스 23, 사파리 5.1.7, 오페라 12.15
    성공: IE8

  9. Cache-Control: no-store
    실패: 사파리 5.1.7, 오페라 12.15
    성공: 크롬 28, 파이어폭스 23, IE8

  10. Cache-Control: no-store
    <body onunload="">
    실패: 오페라 12.15
    성공: 크롬 28, 파이어폭스 23, IE8, 사파리 5.1.7

  11. Cache-Control: no-cache
    실패: 크롬 28, 파이어폭스 23, 사파리 5.1.7, 오페라 12.15
    성공: IE8

  12. Vary: *
    실패: 크롬 28, 파이어폭스 23, IE8, 사파리 5.1.7, 오페라 12.15
    성공: 없음

  13. Pragma: no-cache
    실패: 크롬 28, 파이어폭스 23, IE8, 사파리 5.1.7, 오페라 12.15
    성공: 없음

  14. Cache-Control: private, no-cache, must-revalidate, max-age=0, proxy-revalidate, s-maxage=0
    Expires: Sat, 12 Oct 1991 05:00:00 GMT
    Pragma: no-cache
    Vary: *
    <body onunload="">
    실패: 크롬 28, 파이어폭스 23, 사파리 5.1.7, 오페라 12.15
    성공: IE8

  15. Cache-Control: private, no-cache, must-revalidate, max-age=0, proxy-revalidate, s-maxage=0
    Expires: 0
    Pragma: no-cache
    Vary: *
    <body onunload="">
    실패: 크롬 28, 파이어폭스 23, 사파리 5.1.7, 오페라 12.15
    성공: IE8

  16. Cache-Control: must-revalidate, max-age=0
    실패: 크롬 28, 파이어폭스 23, 사파리 5.1.7, 오페라 12.15
    성공: IE8

  17. Cache-Control: must-revalidate
    Expires: 0
    실패: 크롬 28, 파이어폭스 23, 사파리 5.1.7, 오페라 12.15
    성공: IE8

  18. Cache-Control: must-revalidate
    Expires: Sat, 12 Oct 1991 05:00:00 GMT
    실패: 크롬 28, 파이어폭스 23, 사파리 5.1.7, 오페라 12.15
    성공: IE8

  19. Cache-Control: private, must-revalidate, proxy-revalidate, s-maxage=0
    Pragma: no-cache
    Vary: *
    <body onunload="">
    실패: 크롬 28, 파이어폭스 23, IE8, 사파리 5.1.7, 오페라 12.15
    성공: 없음

HTTPS:

  1. Cache-Control: private, max-age=0, proxy-revalidate, s-maxage=0
    Expires: 0
    <body onunload="">
    실패: 크롬 28, 파이어폭스 23, IE8, 사파리 5.1.7, 오페라 12.15
    성공: 없음

  2. Cache-Control: private, max-age=0, proxy-revalidate, s-maxage=0
    Expires: Sat, 12 Oct 1991 05:00:00 GMT
    <body onunload="">
    실패: 크롬 28, 파이어폭스 23, IE8, 사파리 5.1.7, 오페라 12.15
    성공: 없음

  3. Vary: *
    실패: 크롬 28, 사파리 5.1.7, 오페라 12.15
    성공: FireFox 23, IE8

  4. Pragma: no-cache
    실패: 크롬 28, 사파리 5.1.7, 오페라 12.15
    성공: FireFox 23, IE8

  5. Cache-Control: no-cache
    실패: 크롬 28, 사파리 5.1.7, 오페라 12.15
    성공: FireFox 23, IE8

  6. Cache-Control: private, no-cache, max-age=0, proxy-revalidate, s-maxage=0
    실패: 크롬 28, 사파리 5.1.7, 오페라 12.15
    성공: FireFox 23, IE8

  7. Cache-Control: private, no-cache, max-age=0, proxy-revalidate, s-maxage=0
    Expires: 0
    Pragma: no-cache
    Vary: *
    실패: 크롬 28, 사파리 5.1.7, 오페라 12.15
    성공: FireFox 23, IE8

  8. Cache-Control: private, no-cache, max-age=0, proxy-revalidate, s-maxage=0
    Expires: Sat, 12 Oct 1991 05:00:00 GMT
    Pragma: no-cache
    Vary: *
    실패: 크롬 28, 사파리 5.1.7, 오페라 12.15
    성공: FireFox 23, IE8

  9. Cache-Control: must-revalidate
    실패: 크롬 28, 파이어폭스 23, IE8, 사파리 5.1.7
    성공: 오페라 12.15

  10. Cache-Control: private, must-revalidate, proxy-revalidate, s-maxage=0
    <body onunload="">
    실패: 크롬 28, 파이어폭스 23, IE8, 사파리 5.1.7
    성공: 오페라 12.15

  11. Cache-Control: must-revalidate, max-age=0
    실패: 크롬 28, 파이어폭스 23, 사파리 5.1.7
    성공: IE8, 오페라 12.15

  12. Cache-Control: private, no-cache, must-revalidate, max-age=0, proxy-revalidate, s-maxage=0
    Expires: Sat, 12 Oct 1991 05:00:00 GMT
    Pragma: no-cache
    Vary: *
    <body onunload="">
    실패: 크롬 28, 사파리 5.1.7
    성공: FireFox 23, IE8, Opera 12.15

  13. Cache-Control: private, no-cache, must-revalidate, max-age=0, proxy-revalidate, s-maxage=0
    Expires: 0
    Pragma: no-cache
    Vary: *
    <body onunload="">
    실패: 크롬 28, 사파리 5.1.7
    성공: FireFox 23, IE8, Opera 12.15

  14. Cache-Control: no-store
    실패: 오페라 12.15
    성공: 크롬 28, 파이어폭스 23, IE8, 사파리 5.1.7

  15. Cache-Control: private, no-cache, no-store, max-age=0, proxy-revalidate, s-maxage=0
    Expires: 0
    Pragma: no-cache
    Vary: *
    <body onunload="">
    실패: 오페라 12.15
    성공: 크롬 28, 파이어폭스 23, IE8, 사파리 5.1.7

  16. Cache-Control: private, no-cache, no-store, max-age=0, proxy-revalidate, s-maxage=0
    Expires: Sat, 12 Oct 1991 05:00:00 GMT
    Pragma: no-cache
    Vary: *
    <body onunload="">
    실패: 오페라 12.15
    성공: 크롬 28, 파이어폭스 23, IE8, 사파리 5.1.7

  17. Cache-Control: private, no-cache
    Expires: Sat, 12 Oct 1991 05:00:00 GMT
    Pragma: no-cache
    Vary: *
    실패: 크롬 28, 사파리 5.1.7, 오페라 12.15
    성공: FireFox 23, IE8

  18. Cache-Control: must-revalidate
    Expires: 0
    실패: 크롬 28, 파이어폭스 23, 사파리 5.1.7,
    성공: IE8, 오페라 12.15

  19. Cache-Control: must-revalidate
    Expires: Sat, 12 Oct 1991 05:00:00 GMT
    실패: 크롬 28, 파이어폭스 23, 사파리 5.1.7,
    성공: IE8, 오페라 12.15

  20. Cache-Control: private, must-revalidate, max-age=0, proxy-revalidate, s-maxage=0
    Expires: 0
    <body onunload="">
    실패: 크롬 28, 파이어폭스 23, 사파리 5.1.7,
    성공: IE8, 오페라 12.15

  21. Cache-Control: private, must-revalidate, max-age=0, proxy-revalidate, s-maxage=0
    Expires: Sat, 12 Oct 1991 05:00:00 GMT
    <body onunload="">
    실패: 크롬 28, 파이어폭스 23, 사파리 5.1.7,
    성공: IE8, 오페라 12.15

  22. Cache-Control: private, must-revalidate
    Expires: Sat, 12 Oct 1991 05:00:00 GMT
    Pragma: no-cache
    Vary: *
    실패: 크롬 28, 사파리 5.1.7
    성공: FireFox 23, IE8, Opera 12.15

  23. Cache-Control: no-store, must-revalidate
    실패: 없음
    성공: 크롬 28, 파이어폭스 23, IE8, 사파리 5.1.7, 오페라 12.15


Pacerier

web.config 경로가 유용하다는 것을 알았습니다(답변에 추가하려고 시도했지만 수락되지 않은 것 같아서 여기에 게시)

 <configuration> <system.webServer> <httpProtocol> <customHeaders> <add name="Cache-Control" value="no-cache, no-store, must-revalidate" /> <!-- HTTP 1.1. --> <add name="Pragma" value="no-cache" /> <!-- HTTP 1.0. --> <add name="Expires" value="0" /> <!-- Proxies. --> </customHeaders> </httpProtocol> </system.webServer>

다음은 동일한 작업을 수행하는 express / node.js 방법입니다.

 app.use(function(req, res, next) { res.setHeader('Cache-Control', 'no-cache, no-store, must-revalidate'); res.setHeader('Pragma', 'no-cache'); res.setHeader('Expires', '0'); next(); });

Joseph Connolly

이 페이지의 모든 답변에 여전히 문제가 있음을 발견했습니다. 특히, 나는 그들 중 누구도 뒤로 버튼을 눌러 액세스했을 때 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을 입력할 때 서버에서 페이지가 요청되었습니다. 주소 표시줄에 직접. 이는 '10년 1월 현재 사용 중인 모든 브라우저의 약 99%를 차지합니다.

IE6 및 Opera 9-10에서 뒤로 버튼을 누르면 여전히 캐시된 버전이 로드됩니다. 내가 테스트한 다른 모든 브라우저에서는 서버에서 새 버전을 가져왔습니다. 지금까지 뒤로 버튼을 눌렀을 때 해당 브라우저가 페이지의 캐시된 버전을 반환하지 않도록 하는 헤더 집합을 찾지 못했습니다.

업데이트: 이 답변을 작성한 후 웹 서버가 자신을 HTTP 1.0 서버로 식별하고 있음을 깨달았습니다. 내가 나열한 헤더는 HTTP 1.0 서버의 응답이 브라우저에서 캐시되지 않도록 하기 위한 올바른 헤더입니다. HTTP 1.1 서버의 경우 BalusC의 답변을 참조하십시오 .


Chris Vasselli

약간의 연구 끝에 우리는 대부분의 브라우저를 포함하는 것으로 보이는 다음 헤더 목록을 만들었습니다.

ASP.NET에서는 다음 스니펫을 사용하여 이를 추가했습니다.

 Response.ClearHeaders(); Response.AppendHeader("Cache-Control", "no-cache"); //HTTP 1.1 Response.AppendHeader("Cache-Control", "private"); // HTTP 1.1 Response.AppendHeader("Cache-Control", "no-store"); // HTTP 1.1 Response.AppendHeader("Cache-Control", "must-revalidate"); // HTTP 1.1 Response.AppendHeader("Cache-Control", "max-stale=0"); // HTTP 1.1 Response.AppendHeader("Cache-Control", "post-check=0"); // HTTP 1.1 Response.AppendHeader("Cache-Control", "pre-check=0"); // HTTP 1.1 Response.AppendHeader("Pragma", "no-cache"); // HTTP 1.0 Response.AppendHeader("Expires", "Sat, 26 Jul 1997 05:00:00 GMT"); // HTTP 1.0

출처: http://forums.asp.net/t/1013531.aspx


Edward Wilde

응답에서 pragma 헤더를 사용하는 것은 아내의 이야기입니다. RFC2616은 요청 헤더로만 정의합니다.

http://www.mnot.net/cache_docs/#PRAGMA


Dave Cheney

면책 조항 : @BalusC의 답변을 읽는 것이 좋습니다. 다음 캐싱 튜토리얼을 읽은 후: http://www.mnot.net/cache_docs/ (나도 읽을 것을 권장합니다), 저는 그것이 정확하다고 믿습니다. 그러나 역사적 이유로 (그리고 직접 테스트했기 때문에) 아래에 원래 답변을 포함하겠습니다.


나는 나를 위해 작동하지 않는 PHP에 대한 '허용'답변을 시도했습니다. 그런 다음 약간의 연구를 수행하고 약간의 변형을 찾아 테스트한 결과 효과가 있었습니다. 여기있어:

 header('Cache-Control: no-store, private, no-cache, must-revalidate'); // HTTP/1.1 header('Cache-Control: pre-check=0, post-check=0, max-age=0, max-stale = 0', false); // HTTP/1.1 header('Pragma: public'); header('Expires: Sat, 26 Jul 1997 05:00:00 GMT'); // Date in the past header('Expires: 0', false); header('Last-Modified: '.gmdate('D, d MYH:i:s') . ' GMT'); header ('Pragma: no-cache');

작동해야 합니다. 문제는 헤더의 동일한 부분을 두 번 설정할 때 false 가 전송되지 않으면 헤더 함수가 단순히 이전 header() 호출을 덮어씁니다. Cache-Control 설정할 때 header() 함수 호출에 모든 인수를 넣고 싶지 않은 경우 다음과 같이 해야 합니다.

 header('Cache-Control: this'); header('Cache-Control: and, this', false);

여기에서 더 완전한 문서를 참조하십시오.


Steven Oxley

IE6에 버그가 있습니다.

"Content-Encoding: gzip"이 있는 콘텐츠는 "Cache-Control: no-cache"를 사용하더라도 항상 캐시됩니다.

http://support.microsoft.com/kb/321722

IE6 사용자에 대해 gzip 압축을 비활성화할 수 있습니다("MSIE 6"에 대한 사용자 에이전트 확인).


Edson Medina

ASP.NET Core의 경우 간단한 미들웨어 클래스를 만듭니다.

 public class NoCacheMiddleware { private readonly RequestDelegate m_next; public NoCacheMiddleware( RequestDelegate next ) { m_next = next; } public async Task Invoke( HttpContext httpContext ) { httpContext.Response.OnStarting( ( state ) => { // ref: http://stackoverflow.com/questions/49547/making-sure-a-web-page-is-not-cached-across-all-browsers httpContext.Response.Headers.Append( "Cache-Control", "no-cache, no-store, must-revalidate" ); httpContext.Response.Headers.Append( "Pragma", "no-cache" ); httpContext.Response.Headers.Append( "Expires", "0" ); return Task.FromResult( 0 ); }, null ); await m_next.Invoke( httpContext ); } }

Startup.cs 등록하십시오.

 app.UseMiddleware<NoCacheMiddleware>();

다음 어딘가에 이것을 추가했는지 확인하십시오.

 app.UseStaticFiles();

kspearrin

이러한 지시문은 보안 위험을 완화하지 않습니다. 이는 실제로 UA가 정보를 보유하지 못하도록 하는 것이 아니라 UA가 휘발성 정보를 새로 고치도록 하기 위한 것입니다. 이 유사한 질문을 참조하십시오. 최소한 라우터, 프록시 등이 캐싱 지시를 무시하지 않을 것이라는 보장은 없습니다.

더 긍정적인 점은 컴퓨터에 대한 물리적 액세스, 소프트웨어 설치 등에 관한 정책이 보안 면에서 대부분의 회사보다 훨씬 앞서 있다는 것입니다. 이 정보의 소비자가 일반 대중이라면, 당신이 할 수 있는 유일한 일은 정보가 그들의 기계에 도달하면 그 기계는 당신의 것이 아니라 그들의 책임이라는 것을 이해하도록 돕는 것뿐입니다.


Dustman

HTTP 1.1 용 RFC는 다음을 위한 HTTP 헤더를 추가하는 것이 적절한 방법이라고 말합니다.

캐시 제어: 캐시 없음

이전 브라우저는 HTTP 1.1과 적절하게 호환되지 않는 경우 이를 무시할 수 있습니다. 그것들을 위해 당신은 헤더를 시도할 수 있습니다:

프라그마: 캐시 없음

이것은 HTTP 1.1 브라우저에서도 작동해야 합니다.


Chris Dail

수정된 http 헤더를 1995년의 어떤 날짜로 설정하면 일반적으로 트릭을 수행합니다.

다음은 예입니다.

만료: 1995년 11월 15일 수요일 04:58:08 GMT
최종 수정일: 1995년 11월 15일 수요일 04:58:08 GMT
캐시 제어: 캐시 없음, 재검증 필수

Anders Sandvig

헤더 함수에 대한 PHP 문서 에는 다소 완전한 예제가 있습니다(타사 제공):

 header('Pragma: public'); header("Expires: Sat, 26 Jul 1997 05:00:00 GMT"); // Date in the past header('Last-Modified: '.gmdate('D, d MYH:i:s') . ' GMT'); header('Cache-Control: no-store, no-cache, must-revalidate'); // HTTP/1.1 header('Cache-Control: pre-check=0, post-check=0, max-age=0', false); // HTTP/1.1 header ("Pragma: no-cache"); header("Expires: 0", false);

Grey Panther

SSL을 통한 IE6-IE8 및 MS Office 파일의 cache:no-cache 헤더(및 유사한 값)에서 다운로드 문제가 발생하는 경우, cache:private,no-store 헤더를 사용하고 POST 요청 시 파일을 반환할 수 있습니다. 효과가있다.


Albert

제 경우에는 이것으로 크롬의 문제를 해결합니다.

 <form id="form1" runat="server" autocomplete="off">

사용자가 보안상의 이유로 버튼을 다시 클릭할 때 이전 양식 데이터의 내용을 지워야 하는 경우


user2321638

II7에서 전송되지 않는 캐시 헤더에 대한 많은 질문에 따르면 허용된 답변은 IIS7+에서 작동하지 않는 것으로 보입니다.

등등

헤더를 설정해야 하는 경우 허용되는 답변은 정확하지만 설정 방법은 아닙니다. 이 방법은 IIS7에서 작동합니다.

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

첫 번째 줄은 Cache-controlno-cache 로 설정하고 두 번째 줄은 다른 속성 no-store, must-revalidate


JK.

Pragma: no-cache를 설정하여 모든 브라우저에서 가장 일관되고 최상의 결과를 얻었습니다.


petr k.

BalusC에서 제공하는 답변의 헤더는 브라우저의 뒤로 버튼을 사용할 때 Safari 5(및 이전 버전도 가능)가 브라우저 캐시의 콘텐츠를 표시하는 것을 방지하지 않습니다. 이를 방지하는 방법은 빈 onunload 이벤트 핸들러 속성을 body 태그에 추가하는 것입니다.

 <body onunload="">

이 해킹은 분명히 Safari에서 역방향 캐시를깨뜨립니다. 뒤로 버튼을 클릭할 때 브라우저 간 onload 이벤트가 있습니까?


Tobias

또한 캐싱을 활성화하는 데 사용하는 경우 .htaccess 파일에서 ExpiresDefault 를 재설정해야 합니다.

 ExpiresDefault "access plus 0 seconds"

그런 다음 ExpiresByType 을 사용하여 캐시하려는 파일의 특정 값을 설정할 수 있습니다.

 ExpiresByType image/x-icon "access plus 3 month"

이것은 또한 php 등과 같은 동적 파일이 브라우저에 의해 캐시되고 있고 이유를 알 수 없는 경우에 유용할 수 있습니다. ExpiresDefault 확인하십시오.


BannerMan

헤더 외에도 https 를 통해 페이지를 제공하는 것을 고려하십시오. 많은 브라우저는 기본적으로 https를 캐시하지 않습니다.


Harry

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

yongfa365

BalusC -> ANSWER 를 완료하려면 perl을 사용하는 경우 CGI를 사용하여 HTTP 헤더를 추가할 수 있습니다.

펄 사용:

 Use CGI; sub set_new_query() { binmode STDOUT, ":utf8"; die if defined $query; $query = CGI->new(); print $query->header( -expires => 'Sat, 26 Jul 1997 05:00:00 GMT', -Pragma => 'no-cache', -Cache_Control => join(', ', qw( private no-cache no-store must-revalidate max-age=0 pre-check=0 post-check=0 )) ); }

아파치 httpd.conf 사용

 <FilesMatch "\.(html|htm|js|css|pl)$"> FileETag None <ifModule mod_headers.c> Header unset ETag Header set Cache-Control "max-age=0, no-cache, no-store, must-revalidate" Header set Pragma "no-cache" Header set Expires "Wed, 11 Jan 1984 05:00:00 GMT" </ifModule>

참고: html META를 사용하려고 하면 브라우저에서 무시하고 페이지를 캐시했습니다.


Carlos Escalera Alonso

누군가가 동적 콘텐츠만 캐싱하는 것을 방지하려면 이러한 추가 헤더를 프로그래밍 방식으로 추가해야 한다는 점을 지적하고 싶습니다.

캐시가 없는 헤더를 추가하도록 프로젝트의 구성 파일을 편집했지만 일반적으로 바람직하지 않은 정적 콘텐츠 캐싱도 비활성화되었습니다. 코드에서 응답 헤더를 수정하면 이미지와 스타일 파일이 캐시됩니다.

이것은 매우 분명하지만 여전히 언급할 가치가 있습니다.

그리고 또 다른 주의사항. HttpResponse 클래스의 ClearHeaders 메서드를 사용하는 데 주의하십시오. 부주의하게 사용하면 약간의 멍이 생길 수 있습니다. 나에게 준 것처럼.

ActionFilterAttribute 이벤트에서 리디렉션한 후 모든 헤더를 지우면 TempData 저장소의 모든 세션 데이터와 데이터가 손실됩니다. 작업에서 리디렉션하거나 리디렉션이 발생할 때 헤더를 지우지 않는 것이 더 안전합니다.

두 번째 생각에 ClearHeaders 메서드를 사용하는 것을 권장하지 않습니다. 헤더를 별도로 제거하는 것이 좋습니다. 그리고 Cache-Control 헤더를 올바르게 설정하려면 다음 코드를 사용하고 있습니다.

 filterContext.HttpContext.Response.Cache.SetCacheability(HttpCacheability.NoCache); filterContext.HttpContext.Response.Cache.AppendCacheExtension("no-store, must-revalidate");

user3253726

<head><meta> 요소에는 운이 없었습니다. HTTP 캐시 관련 매개변수를 HTML 문서 외부에 직접 추가하면 실제로 효과가 있습니다.

web.header 호출을 사용하는 Python의 샘플 코드는 다음과 같습니다. 나는 내 개인적인 관련 없는 유틸리티 코드를 의도적으로 수정했습니다.


    웹 가져오기
    수입 시스템
    PERSONAL-UTILITIES 가져오기

    myname = "main.py"

    URL = (
        '/', '메인 클래스'
    )

    메인 = web.application(url, globals())

    렌더 = web.template.render("템플릿/", base="레이아웃", 캐시=거짓)

    클래스 main_class(객체):
        def GET(자신):
            web.header("캐시 제어","캐시 없음, 저장 없음, 재검증해야 함")
            web.header("프라그마", "캐시 없음")
            web.header("만료", "0")
            render.main_form() 반환

        def POST(자신):
            msg = "게시됨:"
            형식 = web.input(함수 = 없음)
            web.header("캐시 제어","캐시 없음, 저장 없음, 재검증해야 함")
            web.header("프라그마", "캐시 없음")
            web.header("만료", "0")
            return render.index_laid_out(인사말 = msg + form.function)

    __name__ == "__main__"인 경우:
        nargs = len(sys.argv)
        # 파이썬 프로그램 이름 뒤에 충분한 인수가 있는지 확인
        nargs != 2인 경우:
            LOG-AND-DIE("%s: 명령줄 오류, nargs=%s, 2이어야 함", myname, nargs)
        # TCP 포트 번호가 숫자인지 확인
        노력하다:
            tcp_port = int(sys.argv[1])
        예외를 제외하고 e:
            LOG-AND-DIE("%s: tcp_port = int(%s) 실패(정수 아님)", myname, sys.argv[1])
        # 다 괜찮아!
        JUST-LOG("%s: 포트 %d에서 실행 중", myname, tcp_port)
        web.httpserver.runsimple(main.wsgifunc(), ("localhost", tcp_port))
        메인.런()


Richard Elkins

캐싱에 대한 사례 연구에 대한 다음 링크를 참조하십시오.

http://securityevaluators.com/knowledge/case_studies/caching/

요약, 기사에 따르면 Cache-Control: no-store 만 Chrome, Firefox 및 IE에서 작동합니다. IE는 다른 컨트롤을 허용하지만 Chrome 및 Firefox는 허용하지 않습니다. 이 링크는 캐싱의 역사와 개념 증명을 문서화한 좋은 읽기 자료입니다.


Paul

저는 이 방법으로 해결했습니다.

2가지 고려 사항:

1) 자바 스크립트 대신 백 클릭시 서버 측 이벤트가 발생하지 않습니다.

2) 쿠키를 읽고 쓰는 자바스크립트가 2개 있습니다.

 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'은 로그아웃 후 -1인 내 ID 값입니다(예: 부울과 같은 다른 것을 사용할 수 있음).

그런 다음 내 페이지에 다음을 추가했습니다. (이것은 백 클릭시 발생합니다)

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

다른 아무것도.

이 솔루션을 사용하면 백 클릭이 모든 페이지에서 활성화되고 동일한 브라우저의 각 페이지에서 로그아웃한 후에만 비활성화됩니다.


elle0087

IIS에서 전체 앱이 캐싱을 얻는 대신 개별 파일을 설정하기 위해 위치 블록을 사용할 수 있습니다.

 <location path="index.html"> <system.webServer> <httpProtocol> <customHeaders> <add name="Cache-Control" value="no-cache" /> </customHeaders> </httpProtocol> </system.webServer> </location>

CodeMind

내 대답이 간단하고 어리석게 들리는지, 아마도 오래전부터 이미 알고 있었을지 모르지만 누군가가 브라우저 뒤로 버튼을 사용하여 귀하의 기록 페이지를 보는 것을 방지하는 것이 귀하의 목표 중 하나이므로 다음을 사용할 수 있습니다.

window.location.replace("https://www.example.com/page-not-to-be-viewed-in-browser-history-back-button.html");

물론 이것은 전체 사이트에서 구현하는 것이 불가능할 수도 있지만 적어도 일부 중요한 페이지에서는 그렇게 할 수 있습니다. 도움이 되었기를 바랍니다.


Antonio Ooi

출처 : http:www.stackoverflow.com/questions/49547/how-do-we-control-web-page-caching-across-all-browsers

반응형