この記事に書いてあること
Spring MVCを使っていて、レスポンスヘッダにno-storeやno-cacheという項目を付与したい場面があったのでメモ。
旧Spring MVCのXML設定は、既存システムを保守するときの参考として残します。以下にSpring Boot 3.5.16で実行したJava版も示します。
前提
- Spring MVC 5.x
- Java11
結論
Spring MVCの現在の書き方では、保存を禁止したいレスポンスに Cache-Control: no-store を設定します。no-cache は再利用する前に検証を求める指示です。個人データを返すAPIの保存を禁止し、公開ヘルプだけは5分間の共有キャッシュを許可する例を比較します。
実行用サンプル
JDK 17とMaven 3.9系で mvn test を実行します。ZIPにはソース全文・テスト・pom.xml・READMEを収録しています。
CacheController.java の全文
package info.syachiku.auditweb;
import java.time.Duration;
import org.springframework.http.CacheControl;
import org.springframework.http.ResponseEntity;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RestController;
@RestController
class CacheController {
@GetMapping("/account/details")
ResponseEntity<String> accountDetails() {
return ResponseEntity.ok()
.cacheControl(CacheControl.noStore())
.body("テスト用の個人データ");
}
@GetMapping("/help")
ResponseEntity<String> help() {
return ResponseEntity.ok()
.cacheControl(CacheControl.maxAge(Duration.ofMinutes(5)).cachePublic())
.body("公開ヘルプ");
}
}MockMvcで /account/details の Cache-Control が no-store、/help が max-age=300, public になることを確認しました。例の個人データはテスト用の固定文字列です。実際の個人データへのアクセス制御は認証・認可で行います。
ここからは旧世代の servlet-context.xml による設定例です。出力はSpringのバージョンと設定に依存します。
Cache-Control: no-cache, no-store Pragma: no-cache Expires: 0
次は旧システムの設定を読み解くための例です。現在の新規設定には先に示した CacheControl を使います。
<interceptors>
<bean id="webContentInterceptor"
class="org.springframework.web.servlet.mvc.WebContentInterceptor">
<property name="cacheSeconds" value="0"/>
<property name="useExpiresHeader" value="true"/>
<property name="useCacheControlHeader" value="true"/>
<property name="useCacheControlNoStore" value="true"/>
</bean>
</interceptors>
なお、servlet-context.xmlの書き方次第では、mvc:interceptorsとしたり、beans:beanとしないといけない場合があります。
ちょっと説明
cacheSeconds
- -1: キャッシュ関連のヘッダーは出力しません。
- 0: no cache 関連のヘッダーが出力されます。
- 1以上: 100を指定した場合、'Cache-Control: max-age=100'というヘッダが出力されます。
useExpiresHeader
trueにすると、Expiresヘッダが出力されます。
Expires: Thu, 01 Jan 1970 00:00:00 GMT
useCacheControlHeader
trueにすると、以下のヘッダが出力されます。
Cache-Control: no-cache
useCacheControlNoStore
trueにすると、以下のヘッダが出力されます。
Cache-Control: no-store
