調査の結果、すべてのブラウザが HTTP キャッシュ ディレクティブを均一に尊重しているわけではないことが判明しました。
セキュリティ上の理由から、アプリケーション内の特定のページが Web ブラウザーによってキャッシュされることを決して望んでいません。これは、少なくとも次のブラウザーで機能する必要があります。
- インターネットエクスプローラー6以上
- Firefox 1.5以上
- サファリ3+
- オペラ9+
- クロム
私たちの要件はセキュリティ テストから生まれました。当社の Web サイトからログアウトした後、[戻る] ボタンを押してキャッシュされたページを表示できます。
ベストアンサー1
導入
言及されているすべてのクライアント (およびプロキシ) で機能する正しい最小ヘッダー セット:
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 プロキシのみに適用されます。
のみを使用して HTTPS 経由でページを提供するときに IE6 とその壊れたキャッシュを気にしない場合はno-store
、 を省略できます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-Control
Expires
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 Servlet または 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 Web 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.
Python/Flask の使用:
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.
Python/Pyramid の使用:
request.response.headerlist.extend(
(
('Cache-Control', 'no-cache, no-store, must-revalidate'),
('Pragma', 'no-cache'),
('Expires', '0')
)
)
Go を使用する場合:
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 ユーティリティが必要):
(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>
Firebaseホスティングの使用firebase.json
:
"headers": [
{ "key": "Cache-Control", "value": "no-cache, no-store, must-revalidate" },
{ "key": "Pragma", "value": "no-cache" },
{ "key": "Expires", "value": "0" }
]
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 メタタグよりも優先されるということです。HTML メタタグは、ページが URL 経由でローカル ディスク ファイル システムから表示される場合にのみ使用されますfile://
。W3 HTML 仕様 5.2.2 章ウェブサーバーにはデフォルト値が含まれる可能性があるため、プログラムで指定しない場合は注意してください。
一般的に、初心者の混乱を避けるためにHTMLメタタグを指定せず、ハードHTTPレスポンスヘッダーに頼る方がよいでしょう。さらに、これらの<meta http-equiv>
タグは具体的には無効HTML5ではhttp-equiv
、HTML5仕様許可されます。
実際のHTTPレスポンスヘッダーの検証
これらを確認するには、Web ブラウザの開発者ツールセットの HTTP トラフィック モニターで確認/デバッグできます。Chrome/Firefox23+/IE9+ で F12 キーを押して、[ネットワーク] または [ネット] タブ パネルを開き、対象の HTTP リクエストをクリックして、HTTP リクエストとレスポンスに関するすべての詳細を表示します。下のスクリーンショットChromeからのものです:
ファイルのダウンロードにもこれらのヘッダーを設定したい
まず、この質問と回答は「Web ページ」(HTML ページ)を対象としており、「ファイルのダウンロード」(PDF、zip、Excel など)を対象としているわけではありません。ファイルをキャッシュしておき、URI パスまたはクエリ文字列のどこかにあるファイル バージョン識別子を使用して、変更されたファイルを強制的に再ダウンロードするようにした方がよいでしょう。いずれにしても、ファイルのダウンロードにこれらのキャッシュなしヘッダーを適用する場合は、HTTP ではなく HTTPS 経由でファイルのダウンロードを提供するときに IE7/8 のバグに注意してください。詳細については、IE は foo.jsf をダウンロードできません。IE はこのインターネット サイトを開くことができませんでした。要求されたサイトは利用できないか、見つかりません。。