こんにちは。田崎です。
みなさん、素敵なコンテンツキャッシュライフを送ってますか?サイトのパフォーマンス向上とサーバーの負荷軽減をしてくれるコンテンツキャッシュは凄く便利でありがたいですよね。5月にも、テックブログでコンテンツキャッシュの2つの新機能:キャッシュ取り込みおよびエラー応答のキャッシュ停止について紹介させていただきました。
しかし、同じオリジンサーバーにはキャッシュさせたなくない、させるべきではないコンテンツもあるかと思います。もしキャッシュさせたくないものをキャッシュしてしまうと、情報漏えい事故になり得ます。IPAでもコンテンツの暴露対策の記事(プロキシキャッシュ対策)が挙げられていましたね。そうならないためにも、キャッシュさせないやり方も知っておくべきだと思い、今回のブログを書いています。
それでは、本日はコンテンツをキャッシュさせない3つの設定方法と確認の方法について紹介します。
確認環境
- オリジンサーバーはIDCFクラウド上に構築
- HTTP/1.1
- Apache/2.4
- Cache-Controlの設定はApache側ではなく、コンテンツ側(PHP)に設定
- IDCFクラウドのコンテンツキャッシュ(CDN)
- ブラウザはGoogle Chrome
キャッシュ確認方法
まず、キャッシュさせない設定の前に、キャッシュされたかの確認方法をCLIとGUIの2パターン使って紹介します。キャッシュさせたいコンテンツに以下ヘッダーを設定しています。
header('Cache-Control: public, max-age=60');
この例では、Cache-Controlヘッダーとmax-ageが設定されています。
Cache-Control: public
このコンテンツはキャッシュしてOKという設定です。max-age=60
キャッシュの有効期限は60秒という設定です。すなわち、60秒間コンテンツがキャッシュされた後は強制的にオリジンサーバーを参照しにいきます。
CLI(Linux/Unix コマンドのcurl)で確認を行う例
$ curl -v http://cachetest01.xxxxxxxxxxxxx/hello2.php > /dev/null > GET /hello2.php HTTP/1.1 > User-Agent: curl/7.15.5 (x86_64-redhat-linux-gnu) libcurl/7.15.5 OpenSSL/0.9.8b zlib/1.2.3 libidn/0.6.5 > Host: cachetest01.xxxxxxxxxxxxx > Accept: */* > < HTTP/1.1 200 OK < Date: Thu, 20 Jul 2017 00:29:02 GMT < Server: ATS < X-Powered-By: PHP/5.4.16 < Cache-Control: public, max-age=60 ★1 < Content-Length: 87 < Content-Type: text/html; charset=UTF-8 < Age: 1 < Connection: keep-alive < Via: http/1.1 xxxxxxxxxxxxxxxxxxxxxxxxxx (ATS [cHs f ]) ★2
★1:設定したCache-Controlヘッダーが表示
★2:キャッシュされているという意味
GUI(Google Chromeブラウザ)で確認を行う例
まずキャッシュ確認の前に、Chromeのメニューより【デベロッパーツール】を開き、【Network】を選択します。
次に、ブラウザから【http://キャッシュサーバーのドメイン名/ファイルのパス】へアクセスして確認します。
▲ブラウザからキャッシュ確認した結果
Response HeadersのVia ヘッダーの末尾が、[cHs f ]となっているので、キャッシュサーバー上にコンテンツがキャッシュされていることを示しています。
補足:Via ヘッダーの見方
Viaヘッダーの見方とその意味について補足します。
Viaヘッダー | キャッシュ | 備考 |
---|---|---|
cHあるいはcR | される | - |
cH cRとなっていない最終fの後が空欄 | されない | キャッシュ領域への書き込みなし |
cSとなりRefreshされる | される※ | ※キャッシュはされるが、期限切れ状態 |
キャッシュさせないための設定
では、本題のキャッシュをさせないようにする設定ですが、「private」、「no-cache」と「no-store」等3種類あります。それぞれの意味は次の通りです。
1. private
レスポンスがひとりのユーザーのため(private)のものであり、共有キャッシュに保存してはいけない。 つまり、プライベートなんだからそもそもキャッシュするのは論外!!
2. no-cache
オリジンサーバーの確認無しに勝手にキャッシュしてはいけない。つまり、勝手に再利用するな!毎回聞きに来い!ノー、キャッシュ!!
3. no-store
リクエスト、レスポンスをキャッシュしてはいけない。つまり、キャッシュに記録するんじゃないぞ!ノー、ストア!!
今回はCache-Controlヘッダーの「public, max-age=60」を「private」に変更して、キャッシュ状態を確認してみます。
header('Cache-Control: private');
CLI(Linux/Unix コマンドのcurl)で確認した結果
$ curl -v http://cachetest01.xxxxxxxxxxxxx/hello2.php > /dev/null > GET /hello2.php HTTP/1.1 > User-Agent: curl/7.15.5 (x86_64-redhat-linux-gnu) libcurl/7.15.5 OpenSSL/0.9.8b zlib/1.2.3 libidn/0.6.5 > Host: cachetest01.xxxxxxxxxxxxx > Accept: */* > < HTTP/1.1 200 OK < Date: Thu, 20 Jul 2017 02:12:23 GMT < Server: ATS < X-Powered-By: PHP/5.4.16 < Cache-Control: private ★1 < Content-Length: 87 < Content-Type: text/html; charset=UTF-8 < Age: 0 < Connection: keep-alive < Via: http/1.1 xxxxxxxxxxxxxxxxxxxxxxxxxx (ATS [cMsSf ]) ★2
★1:変更したprivateが表示
★2:キャッシュされてない
GUI(Google Chromeブラウザ)で確認した結果
Response HeadersのVia ヘッダーの末尾が、[cMsSf ]となっているので、キャッシュサーバー上にコンテンツがキャッシュされていないことを示しています。
▲ブラウザからキャッシュ確認した結果
Cache-Controlヘッダーに複数指定した場合
今までキャッシュさせる方法とキャッシュさせない方法を紹介しました。では1つのCache-Controlヘッダーに、キャッシュさせる「public, max-age=60」とキャッシュさせない「private」の両方の値を指定した以下のケースではどうなるでしょうか。
header('Cache-Control: private,public,max-age=60');
CLI/GUIで確認した結果
< Cache-Control: private,public,max-age=60 (略) < Via: http/1.1 xxxxxxxxxxxxxxxxxxxxxxxxxx (ATS [cMsSf ])
▲ブラウザからキャッシュ確認した結果
CLI/GUI共に表示上ではCache-Controlに設定した全ての値が見えますが、「private」が優先されてキャッシュは無効化されます。「private」の他にIPA推奨ヘッダーである「no-cache」、「no-store」でも確認したところ、同じ結果でキャッシュは無効化されます。また、IPAでこれらキャッシュさせない値(private、no-cache、no-store、must-revalidate)をすべて指定した場合でも構わないと記載しているとおり、結果は同じでキャッシュはされません。
まとめ
今回は、コンテンツをキャッシュさせない3つの設定方法(private, no-cacheとno-store)とその確認方法について紹介しました。
キャッシュの有効化と無効化の両方のやり方を知ることで、オリジンサーバーの管理品質が向上され、大切なコンテンツを守ることができます。キャッシュさせたが故に情報漏えい事故が起きてしまった後では遅いので、この機会に一度キャッシュの設定を見直してみてはいかがでしょうか。
- キャッシュを無効化させたい場合、Cache-Controlの設定に「private」を設定してください。
- ヘッダーを変更したら必ずキャッシュ削除を行って、キャッシュの有無確認をしてください。
次回は、コンテンツキャッシュの機能アップデートについて紹介します。ありがとうございました!