逸出Freemarker的模板,我们可以使用转义指令的逃逸自动应用到包含块内的所有插值:默认在Freemarker的
<#escape x as x?html>
<#-- name is escaped as html -->
Hallo, ${name}
</#escape>
有没有一种方法以编程方式达到类似的效果,定义了默认转义应用于模板中的所有插值,包括那些外部转义指令?
谢谢。
逸出Freemarker的模板,我们可以使用转义指令的逃逸自动应用到包含块内的所有插值:默认在Freemarker的
<#escape x as x?html>
<#-- name is escaped as html -->
Hallo, ${name}
</#escape>
有没有一种方法以编程方式达到类似的效果,定义了默认转义应用于模板中的所有插值,包括那些外部转义指令?
谢谢。
有一个解决方案,虽然它不是微不足道的。您可以创建一个特殊的TemplateLoader来封装其他模板加载器,并在模板源文本的序言中注入#escape x作为x?html>,并添加为它的结尾。
明显的缺点: - 列数在第一行会被甩出 - 如果您的模板与< #ftl>声明开始,你需要在它后面插入< #escape>。
为了详细说明阿提拉的回答是:你可以使用一个类像this one,然后换你的模板加载器是这样的:
final TemplateLoader templateLoader = new ClassTemplateLoader(this.getClass(), templatePath) {
/**
* Replaces the normal template reader with something that changes the default
* escaping to HTML as to avoid XSS attacks.
*/
@Override
public Reader getReader(Object templateSource, String encoding) throws IOException {
return new WrappingReader(super.getReader(templateSource, encoding), "<#escape x as x?html>", "</#escape>");
}
};
如果不包括增加的部分换行符你没有得到的行编号问题。尽管如此,您无法使用<#ftl>/[#ftl]。
实际上您并不需要WrappingReader来添加换码。你可以在任何TemplateLoader周围创建一个装饰器,在模板中读入一个String,在escapes中包装模板文本,然后返回一个读取结果String的StringReader。要看看如何完成看看here。我发现的唯一问题是,如果你使用这种方法并从类路径中包含spring.ftl宏,它们将会炸毁,因为它们在顶部有一个< #ftl>声明。但是,您可以简单地将spring.ftl复制到您的模板路径中,并删除声明(以及所有转义指令,因为您将默认转义)。
如果您正在使用< #include parse = false ... />在模板中包含HTML,则链接中的建议TemplateLoaders需要稍微调整。
此外,您需要复制spring.ftl并使用您自己的副本与< #ftl ..>指令顶部删除像汤姆说。
以下效果很好,尽管有点粗糙(使用番石榴过度公地1-10)
@Override
public Reader getReader(Object pTemplateSource, String pEncoding) throws IOException {
Reader tReader = delegate.getReader(pTemplateSource, pEncoding);
try {
String tTemplateText = CharStreams.toString(tReader);
//only include files ending with "ftl", as we may have some parse=false on included html files
if (pTemplateSource.toString().endsWith("ftl")) {
return new StringReader(ESCAPE_PREFIX + tTemplateText + ESCAPE_SUFFIX);
}
return new StringReader(tTemplateText);
} finally {
Closeables.closeQuietly(tReader);
}
}
由于2.3.24每个模板具有相关联的对象freemarker.core.OutputFormat
,指定是否以及如何${...}
(和#{...}
)逃脱。提供HTML,XML和RTF的OuputFormat
开箱即用,但您也可以定义自己的格式。当默认选择OutputFormat
转义时,则可以像${foo?no_esc}
那样显式地防止转义。
有几种方法可以将模板与您想要的OutputFormat
相关联。对于HTML和XML转义,推荐的方法是将recognize_standard_file_extensions
配置设置设置为true
,然后将ftlh
文件扩展名用于HTML,ftlx
文件扩展名用于XML模板。您还可以使用template_configurers
设置将OutputFormat
-s与基于任意模板名称(模板路径)模式的模板相关联。最后同样重要的是,您可以设置全局默认输出格式,如configuration.setOutputFormat(HTMLOutputFormat.INSTANCE)
。您也可以覆盖模板顶部的输出格式<#ftl output_format='HTML'>
,尽管它应该很少使用。
相关文档页数:http://freemarker.org/docs/dgui_misc_autoescaping.html,http://freemarker.org/docs/pgui_config_outputformatsautoesc.html
彼得链接WrappingReader类不工作了。新位置:http://sourceforge.net/p/metadata-net/code/HEAD/tree/shared/trunk/util/src/main/java/au/edu/uq/itee/maenad/util/WrappingReader。 java – 2013-09-26 14:41:02
@StefanHaberl:我更新了答案 - 谢谢。 – 2013-09-27 04:41:32