在不进行依赖版本升级,同时避免对已有类进行重写,可以参考下列处理:
Configuration
在配置类FreeMarkerConfigurer
中使用,在配置类的bean
初始化方法afterPropertiesSet
中,若Configuration
还未设置,则使用createConfiguration
方法创建Configuration
.
SpringBoot
自动配置FreeMarkerConfigurer
,如下图所示:
其使用了@ConditionalOnMissingBean(FreeMarkerConfig.class)
,故可以使用我们自己定义的FreeMarkerConfigurer
,通过自定义的FreeMarkerConfigurer
中配置对应的Configuration
,解决Freemarker 模板注入漏洞.
自定义配置FreeMarkerConfigurer
代码示例如下:
@Configuration(proxyBeanMethods = false)
@ConditionalOnWebApplication(type = ConditionalOnWebApplication.Type.SERVLET)
@ConditionalOnClass({Servlet.class, FreeMarkerConfigurer.class})
public class FreeMarkerServletWebConfigurer {
private final FreeMarkerProperties properties;
public FreeMarkerServletWebConfigurer(FreeMarkerProperties properties) {
this.properties = properties;
}
protected void applyProperties(FreeMarkerConfigurationFactory factory) {
factory.setTemplateLoaderPaths(this.properties.getTemplateLoaderPath());
factory.setPreferFileSystemAccess(this.properties.isPreferFileSystemAccess());
factory.setDefaultEncoding(this.properties.getCharsetName());
Properties settings = new Properties();
settings.put("recognize_standard_file_extensions", "true");
settings.putAll(this.properties.getSettings());
factory.setFreemarkerSettings(settings);
}
@Bean
FreeMarkerConfigurer freeMarkerConfigurer() throws IOException, TemplateException {
FreeMarkerConfigurer configurer = new FreeMarkerConfigurer();
freemarker.template.Configuration configuration = configurer.createConfiguration();
// 通过设置TemplateClassResolver.SAFER_RESOLVER避免注入漏洞.
configuration.setNewBuiltinClassResolver(TemplateClassResolver.SAFER_RESOLVER);
configurer.setConfiguration(configuration);
applyProperties(configurer);
return configurer;
}
}