Spring MVC VersionResourceResolver中断CSS相对URL

zazmityj  于 2023-04-12  发布在  Spring
关注(0)|答案(3)|浏览(113)

我正在Sping Boot 1.2.2中使用VersionResourceResolver进行缓存崩溃。不幸的是,它认为操纵CSS文件中指定的URI是聪明的。
以Twitters Bootstrap为例,它在CSS文件所在目录的上方目录中查找字体。

@font-face {
  font-family: 'Glyphicons Halflings';

  src: url('../fonts/glyphicons-halflings-regular.eot');
  src: url('../fonts/glyphicons-halflings-regular.eot?#iefix') format('embedded-opentype'), url('../fonts/glyphicons-halflings-regular.woff2') format('woff2'), url('../fonts/glyphicons-halflings-regular.woff') format('woff'), url('../fonts/glyphicons-halflings-regular.ttf') format('truetype'), url('../fonts/glyphicons-halflings-regular.svg#glyphicons_halflingsregular') format('svg');
}

如果没有VersionResourceResolver,它会像预期的那样工作:

GET http://example.com/res/css/bootstrap.min.css
GET http://example.com/res/fonts/glyphicons-halflings-regular.woff

现在我添加VersionResourceResolver:

@Override
public void addResourceHandlers(ResourceHandlerRegistry registry) {
    registry.addResourceHandler("/res/**")
            .addResourceLocations("/resources/")
            .setCachePeriod(CACHE_SECONDS)
            .resourceChain(true)
                .addResolver(new VersionResourceResolver()                      
                .addFixedVersionStrategy(buildVersion, "/**/"))
                .addResolver(new PathResourceResolver());       
}

现在发生的是:

GET http://example.com/res/085a8/css/bootstrap.min.css
GET http://example.com/res/085a8/css/fonts/glyphicons-halflings-regular.woff

那么,为什么会发生这种情况呢?因为有人篡改了CSS文件中的URI:

@font-face {
  font-family: 'Glyphicons Halflings';

  src: url('085a8/../fonts/glyphicons-halflings-regular.eot');
  src: url('../fonts/glyphicons-halflings-regular.eot?#iefix') format('embedded-opentype'), url('085a8/../fonts/glyphicons-halflings-regular.woff2') format('woff2'), url('085a8/../fonts/glyphicons-halflings-regular.woff') format('woff'), url('085a8/../fonts/glyphicons-halflings-regular.ttf') format('truetype'), url('../fonts/glyphicons-halflings-regular.svg#glyphicons_halflingsregular') format('svg');
}

Bootstrap只是一个例子。几乎所有(奇怪的是不是所有)CSS资源中指定的URI都会发生这种情况。使用Spring的CssLinkResourceTransformer没有帮助。那么,我如何告诉Spring不要操作CSS文件?
编辑:我发现,Spring调用了CssLinkResourceTransformer。但我没有在任何地方指定它。可能Sping Boot 在某个地方自动配置了它。

03-05 16:12:47.711 TRACE 11064 --- [nio-8080-exec-2] o.s.w.s.r.CssLinkResourceTransformer     : Transforming resource: ServletContext resource [/resources/css/bootstrap.min.css]
2015-03-05 16:12:47.716 TRACE 11064 --- [nio-8080-exec-2] o.s.w.s.r.CssLinkResourceTransformer     : Link modified: 77a6e2aa77283c05d58f4ab52102f55684b6fb04/../fonts/glyphicons-halflings-regular.eot (original: ../fonts/glyphicons-halflings-regular.eot)
2015-03-05 16:12:47.716 TRACE 11064 --- [nio-8080-exec-2] o.s.w.s.r.CssLinkResourceTransformer     : Link not modified: ../fonts/glyphicons-halflings-regular.eot?#iefix
2015-03-05 16:12:47.717 TRACE 11064 --- [nio-8080-exec-2] o.s.w.s.r.CssLinkResourceTransformer     : Link modified: 77a6e2aa77283c05d58f4ab52102f55684b6fb04/../fonts/glyphicons-halflings-regular.woff2 (original: ../fonts/glyphicons-halflings-regular.woff2)
2015-03-05 16:12:47.718 TRACE 11064 --- [nio-8080-exec-2] o.s.w.s.r.CssLinkResourceTransformer     : Link modified: 77a6e2aa77283c05d58f4ab52102f55684b6fb04/../fonts/glyphicons-halflings-regular.woff (original: ../fonts/glyphicons-halflings-regular.woff)
2015-03-05 16:12:47.719 TRACE 11064 --- [nio-8080-exec-2] o.s.w.s.r.CssLinkResourceTransformer     : Link modified: 77a6e2aa77283c05d58f4ab52102f55684b6fb04/../fonts/glyphicons-halflings-regular.ttf (original: ../fonts/glyphicons-halflings-regular.ttf)
2015-03-05 16:12:47.719 TRACE 11064 --- [nio-8080-exec-2] o.s.w.s.r.CssLinkResourceTransformer     : Link not modified: ../fonts/glyphicons-halflings-regular.svg#glyphicons_halflingsregular

Edit 2:Spring会自动创建一个CssLinkResourceTransformer,如果你注册了一个资源链-.-的话,请参见https://github.com/spring-projects/spring-framework/blob/master/spring-webmvc/src/main/java/org/springframework/web/servlet/config/annotation/ResourceChainRegistration.java#L112

bsxbgnwa

bsxbgnwa1#

Spring 4.1+中的资源处理

您正在使用的VersionStrategy FixedVersionStrategy是为处理文件名以加载JavaScript模块的JavaScript模块加载器定制的。
由于你使用的是JavaScript模块加载器(require.js),使用ContentVersionStrategy用于CSS/images和FixedVersionStrategy用于JS更适合你的应用程序。所以将你的配置改为这样应该可以解决这个问题:

@Override
public void addResourceHandlers(ResourceHandlerRegistry registry) {

    VersionResourceResolver versionResolver = new VersionResourceResolver()
            .addFixedVersionStrategy(version, "/**/*.js")
            .addContentVersionStrategy(version, "/**/*.css", "/**/*.png");

    registry.addResourceHandler("/res/**")
            .addResourceLocations("/resources/")
            .setCachePeriod(CACHE_SECONDS)
            .resourceChain(true)
                .addResolver(versionResolver);
}

请注意,您不需要注册PathResourceResolverCssLinkResourceTransformer,因为通过检查您的配置即可完成(您已经通过阅读源代码了解了这一点)。
现在,为了更好地了解该特性,我建议您阅读this blog post并查看this example application
SPR-12669 JIRA问题
实际上,这个问题与你的用例无关,本质上也不是一个bug。Guillaume创建了WUIC project,我们正在讨论在Spring项目中更好地集成这个资产管道的方法。所以作为一个框架开发人员,他正在为WUIC用户寻找更多的灵活性-资源处理功能本身工作正常。
您所描述的解决方法并不是为在应用程序中使用而设计的,因为您没有充分的理由而不是依赖Spring的默认值来手动进行大量的管道工作。
另外,请注意,我们在这里讨论的默认值是由Spring Framework设置的,而不是由Sping Boot 设置的。Spring Boot“仅”自动配置已知位置以服务静态资源。

qyzbxkaa

qyzbxkaa2#

这种行为的原因是,如果你创建一个ResourceChain,Spring会自动创建一个CssLinkResourceTransformer。你可以在他们的源代码中看到它。这是他们框架中的默认配置。
不幸的是,在我的例子中,它破坏了CSS文件中的相对路径。为了避免CssLinkResourceTransformer的默认配置,你需要自己做ResourceHandling。例如这个way(不推荐!)。

azpvetkf

azpvetkf3#

我在重写CSS文件中的相对路径时遇到了类似的问题。我不得不禁用它,因为在PROD上,我的应用程序是在子路径上提供的(我的意思是“my.beautiful.app.com/myapproute”)
我通过创建一个扩展CssLinkResourceTransformer并禁用其转换的新类来解决这个问题。我知道,这不是一个优雅的解决方案,但简单有效。
下面是我创建的类:

public class CssLinkResourceTransformerDeActivator extends CssLinkResourceTransformer {
@Override
public Resource transform(HttpServletRequest request, Resource resource, ResourceTransformerChain transformerChain)
        throws IOException {
    return transformerChain.transform(request, resource);
}

}
这是我的MvcConfig

@Configuration
public class MvcConfig implements WebMvcConfigurer {
    @Override
    public void addResourceHandlers(ResourceHandlerRegistry registry) {
        registry.addResourceHandler("/js/**", "/css/**", "/fonts/**")
                .addResourceLocations("classpath:/static/js/", "classpath:/static/css/", "classpath:/static/fonts/")
                .resourceChain(true)
                .addTransformer(new CssLinkResourceTransformerDeActivator())
                .addResolver(new VersionResourceResolver().addContentVersionStrategy("/**"));
    }

    @Bean
    public ResourceUrlEncodingFilter resourceUrlEncodingFilter() {
        return new ResourceUrlEncodingFilter();
    }
}

相关问题