Spring Boot应用缓存控制配置问题:公共资源缓存及敏感数据禁缓存
我来帮你一步步解决这个问题。你现在能看到304响应但看不到Cache-Control头,主要是因为当前配置没区分开静态资源和敏感内容的缓存策略,而且Spring Security可能覆盖了Spring Boot默认的资源缓存头。下面是具体的解决方案:
1. 补全Spring Boot静态资源缓存配置
首先在application.properties(或application.yml)里完善静态资源的缓存规则,明确指定缓存时长和公开属性:
# 保留你的原有配置 spring.main.banner-mode=off spring.main.log-startup-info=false # 静态资源缓存配置:缓存一周(604800秒) spring.resources.cache.cachecontrol.max-age=604800s spring.resources.cache.cachecontrol.public=true # 静态资源路径(默认已包含classpath:/static/、classpath:/public/等,可按需补充) spring.resources.static-locations=classpath:/static/,classpath:/public/
2. 配置Spring Security区分缓存策略
光靠Spring Boot的资源配置还不够,因为Spring Security会对所有请求的响应头做统一处理,所以需要在Security配置里针对静态资源和敏感内容分别设置Cache-Control头:
如果你用的是Spring Boot 2.7及以下(WebSecurityConfigurerAdapter未弃用):
import org.springframework.context.annotation.Configuration; import org.springframework.security.config.annotation.web.builders.HttpSecurity; import org.springframework.security.config.annotation.web.configuration.EnableWebSecurity; import org.springframework.security.config.annotation.web.configuration.WebSecurityConfigurerAdapter; import org.springframework.security.web.header.writers.CacheControlHeadersWriter; import org.springframework.security.web.header.writers.DelegatingRequestMatcherHeaderWriter; import org.springframework.security.web.util.matcher.AntPathRequestMatcher; import org.springframework.security.web.util.matcher.NegatedRequestMatcher; import org.springframework.security.web.util.matcher.OrRequestMatcher; @Configuration @EnableWebSecurity public class SecurityConfig extends WebSecurityConfigurerAdapter { @Override protected void configure(HttpSecurity http) throws Exception { // 允许静态资源无需认证即可访问 http.authorizeRequests() .antMatchers("/images/**", "/js/**", "/css/**").permitAll() .anyRequest().authenticated(); // 配置静态资源的缓存头:公开缓存,有效期一周 CacheControlHeadersWriter staticCacheWriter = new CacheControlHeadersWriter(); staticCacheWriter.setCacheControl("public, max-age=604800"); // 配置敏感内容的缓存头:禁止缓存 CacheControlHeadersWriter sensitiveCacheWriter = new CacheControlHeadersWriter(); sensitiveCacheWriter.setCacheControl("no-cache, no-store, must-revalidate"); // 给不同路径绑定对应的缓存头 http.headers() .addHeaderWriter(new DelegatingRequestMatcherHeaderWriter( new OrRequestMatcher( new AntPathRequestMatcher("/images/**"), new AntPathRequestMatcher("/js/**"), new AntPathRequestMatcher("/css/**") ), staticCacheWriter )) .addHeaderWriter(new DelegatingRequestMatcherHeaderWriter( new NegatedRequestMatcher(new OrRequestMatcher( new AntPathRequestMatcher("/images/**"), new AntPathRequestMatcher("/js/**"), new AntPathRequestMatcher("/css/**") )), sensitiveCacheWriter )); } }
如果你用的是Spring Boot 2.7+(推荐使用SecurityFilterChain):
import org.springframework.context.annotation.Bean; import org.springframework.context.annotation.Configuration; import org.springframework.security.config.annotation.web.builders.HttpSecurity; import org.springframework.security.web.SecurityFilterChain; import org.springframework.security.web.header.writers.CacheControlHeadersWriter; import org.springframework.security.web.header.writers.DelegatingRequestMatcherHeaderWriter; import org.springframework.security.web.util.matcher.AntPathRequestMatcher; import org.springframework.security.web.util.matcher.NegatedRequestMatcher; import org.springframework.security.web.util.matcher.OrRequestMatcher; @Configuration public class SecurityConfig { @Bean public SecurityFilterChain securityFilterChain(HttpSecurity http) throws Exception { // 配置权限规则:静态资源放行,其他请求需认证 http.authorizeRequests(auth -> auth .antMatchers("/images/**", "/js/**", "/css/**").permitAll() .anyRequest().authenticated() ); // 静态资源缓存策略 CacheControlHeadersWriter staticCacheWriter = new CacheControlHeadersWriter(); staticCacheWriter.setCacheControl("public, max-age=604800"); // 敏感内容缓存策略 CacheControlHeadersWriter sensitiveCacheWriter = new CacheControlHeadersWriter(); sensitiveCacheWriter.setCacheControl("no-cache, no-store, must-revalidate"); // 绑定路径与缓存头 http.headers(headers -> headers .addHeaderWriter(new DelegatingRequestMatcherHeaderWriter( new OrRequestMatcher( new AntPathRequestMatcher("/images/**"), new AntPathRequestMatcher("/js/**"), new AntPathRequestMatcher("/css/**") ), staticCacheWriter )) .addHeaderWriter(new DelegatingRequestMatcherHeaderWriter( new NegatedRequestMatcher(new OrRequestMatcher( new AntPathRequestMatcher("/images/**"), new AntPathRequestMatcher("/js/**"), new AntPathRequestMatcher("/css/**") )), sensitiveCacheWriter )) ); return http.build(); } }
3. 验证配置效果
配置完成后重启应用,在Chrome网络面板中:
- 访问静态资源(比如
/images/logo.png),正常刷新页面(不要用Ctrl+F5强制刷新),查看响应头应该能看到Cache-Control: public, max-age=604800; - 访问敏感接口(比如用户信息接口),响应头会显示
Cache-Control: no-cache, no-store, must-revalidate; - 304响应是协商缓存的正常表现,它和Cache-Control强制缓存可以共存,浏览器会优先遵循Cache-Control的规则。
为什么之前看不到Cache-Control头?
主要是因为Spring Security的默认配置会对所有响应的缓存头做限制,覆盖了Spring Boot的资源缓存配置。通过上面的配置,我们明确给不同路径指定了对应的缓存策略,就能让响应头正确输出了。
内容的提问来源于stack exchange,提问作者vibetribe93
相关产品推荐
相关产品推荐

