【问题标题】:How to remove Expires header with Spring cache control如何使用 Spring 缓存控制删除 Expires 标头
【发布时间】:2016-03-16 00:36:54
【问题描述】:

Spring Security 默认添加以下缓存头:

Cache-Control: no-cache, no-store, max-age=0, must-revalidate
Pragma: no-cache
Expires: 0

这对我们的 HTML 页面来说是一个很好的设置。对于静态资源(图像、CSS 等),我们希望将它们缓存起来。根据Spring documentation可以这样配置:

@EnableWebMvc
public class WebMvcConfiguration extends WebMvcConfigurerAdapter {

    @Override
    public void addResourceHandlers(ResourceHandlerRegistry registry) {
        registry
            .addResourceHandler("/resources/**")
            .addResourceLocations("/resources/")
            .setCachePeriod(31556926);
    }
}

这会产生以下 HTTP 标头:

Cache-Control: max-age=604800
Pragma: 
Expires: 0

这很好,除了 Expires 标头,它仍然指示不应缓存文档。 (标准规定max-age 优先于Expires。但我们的中间缓存仍将其视为不可缓存。)

我们如何删除可缓存文档的Expires 标头(或将其设置为空白)?如果我们配置了缓存周期,为什么Spring不删除它?

【问题讨论】:

  • 你用的是什么版本的spring-web?如果您使用的是 spring-web-4.2.5.RELEASE.jar ,您可能会遇到jira.spring.io/browse/SPR-14005 你能看看 spring-web-4.2.4.RELEASE.jar 是否出现同样的问题
  • 我们仍然是 4.2.4。所以它与 SPR-14005 无关。然而,在一个 bug 的 cmets 中,有一个如何从 Spring Security 中排除某些资源的示例。这对我们来说是一个可行的解决方案。你想添加是作为答案吗?无论如何感谢您的链接。
  • 感谢您的回复和反馈。请不要在该 JIRA 上使用解决方法。详情见我的回答

标签: java spring http spring-mvc spring-security


【解决方案1】:

这似乎与spring-security#3759 有关。您可以通过忽略在(有些不相关的)SPR-14005 上列出的特定 URL 来解决此问题。但是,不建议这样做(即使 URL 指向静态资源),因为这意味着 URL 的所有安全性都被禁用。

相反,用户应考虑使用此解决方法:

@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);
    }
}

当 Spring Security 4.1 发布时,spring-security#3759 将得到修复,这应该不是问题。

【讨论】:

    【解决方案2】:

    ResourceHttpRequestHandler.useExpriresHeader 设置为false

    不幸的是,配置对象ResourceHandlerRegistry 中没有这样的标志。所以你需要自己做:

    以下只是一个想法,我没有检查这个方法除了ResourceHttpRequestHandler之外没有配置任何其他HandlerMapping

    @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;
    }
    

    【讨论】:

    • 恐怕默认是false。此外,useExpiresHeader 已被弃用。所以这段代码不会改变任何东西。我的调试还表明 Spring Security 在请求处理的早期插入了 Expires 标头。所以ResourceHttpRequestHandler 需要主动取消设置。将其设置为 true 甚至可能更有意义...
    猜你喜欢
    • 1970-01-01
    • 2011-04-26
    • 2011-02-05
    • 2012-04-26
    • 1970-01-01
    • 2017-01-10
    • 2015-02-23
    • 2011-01-13
    • 1970-01-01
    相关资源
    最近更新 更多