2009-08-12 58 views
10

逸出Freemarker的模板,我们可以使用转义指令的逃逸自动应用到包含块内的所有插值:默认在Freemarker的

<#escape x as x?html> 
    <#-- name is escaped as html --> 
    Hallo, ${name} 
</#escape> 

有没有一种方法以编程方式达到类似的效果,定义了默认转义应用于模板中的所有插值,包括那些外部转义指令?

谢谢。

回答

2

有一个解决方案,虽然它不是微不足道的。您可以创建一个特殊的TemplateLoader来封装其他模板加载器,并在模板源文本的序言中注入#escape x作为x?html>,并添加为它的结尾。

明显的缺点: - 列数在第一行会被甩出 - 如果您的模板与< #ftl>声明开始,你需要在它后面插入< #escape>。

5

为了详细说明阿提拉的回答是:你可以使用一个类像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]。

+0

彼得链接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

+0

@StefanHaberl:我更新了答案 - 谢谢。 – 2013-09-27 04:41:32

1

实际上您并不需要WrappingReader来添加换码。你可以在任何TemplateLoader周围创建一个装饰器,在模板中读入一个String,在escapes中包装模板文本,然后返回一个读取结果String的StringReader。要看看如何完成看看here。我发现的唯一问题是,如果你使用这种方法并从类路径中包含spring.ftl宏,它们将会炸毁,因为它们在顶部有一个< #ftl>声明。但是,您可以简单地将spring.ftl复制到您的模板路径中,并删除声明(以及所有转义指令,因为您将默认转义)。

2

如果您正在使用< #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); 
    } 
} 
3

由于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.htmlhttp://freemarker.org/docs/pgui_config_outputformatsautoesc.html