Reputation: 78795
Spring Security adds the following cache headers by default:
Cache-Control: no-cache, no-store, max-age=0, must-revalidate
Pragma: no-cache
Expires: 0
That's a good setting for our HTML pages. For static resources (images, CSS etc.) we would like to have them cached. According to the Spring documentation, it can be configured like this:
@EnableWebMvc
public class WebMvcConfiguration extends WebMvcConfigurerAdapter {
@Override
public void addResourceHandlers(ResourceHandlerRegistry registry) {
registry
.addResourceHandler("/resources/**")
.addResourceLocations("/resources/")
.setCachePeriod(31556926);
}
}
That results in the following HTTP headers:
Cache-Control: max-age=604800
Pragma:
Expires: 0
That's good except for the Expires
header, which still indicates that document should not be cached. (The standard says that max-age
takes precedence over Expires
. But our intermediate cache still treats it as non cacheable.)
How can we remove the Expires
header (or set it to blank) for cacheable documents? Why doesn't Spring remove it if we configure a cache period?
Upvotes: 1
Views: 3342
Reputation: 21720
This appears to be related to spring-security#3759. You can work around this by ignoring specific URLs as listed on (somewhat unrelated) SPR-14005. However, this is not advised (even if the URLs point to static resources) since it means all security is disabled for the URLs.
Instead, users should consider using this workaround:
@EnableWebSecurity
public class WebSecurityConfig extends WebSecurityConfigurerAdapter {
@Override
protected void configure(HttpSecurity http) throws Exception {
RequestMatcher notResourcesMatcher = new NegatedRequestMatcher(new AntPathRequestMatcher("/resources/**"));
HeaderWriter notResourcesHeaderWriter = new DelegatingRequestMatcherHeaderWriter(notResourcesMatcher , new CacheControlHeadersWriter());
http
.headers()
.cacheControl().disable()
.addHeaderWriter(notResourcesHeaderWriter);
}
}
When Spring Security 4.1 is released spring-security#3759 will be fixed and this should not be an issue.
Upvotes: 1
Reputation: 120761
Set ResourceHttpRequestHandler.useExpriresHeader
to false
.
Unfortunaly there is no such flag in the configuration object ResourceHandlerRegistry
. So you need to do it on your own:
The following is just an idea, I have not checked that this method does not configure any other HandlerMapping
than the ResourceHttpRequestHandler
@Override
@Bean
public HandlerMapping resourceHandlerMapping() {
ResourceHandlerRegistry registry = new ResourceHandlerRegistry(this.applicationContext, this.servletContext);
addResourceHandlers(registry);
AbstractHandlerMapping handlerMapping = registry.getHandlerMapping();
if (handlerMapping != null) {
handlerMapping.setPathMatcher(mvcPathMatcher());
handlerMapping.setUrlPathHelper(mvcUrlPathHelper());
handlerMapping.setInterceptors(new HandlerInterceptor[] {
new ResourceUrlProviderExposingInterceptor(mvcResourceUrlProvider())});
//this line!!!:
((ResourceHttpRequestHandler)handlerMapping).setUseExpiresHeader(false);
}
else {
handlerMapping = new EmptyHandlerMapping();
}
return handlerMapping;
}
Upvotes: 0