10

在 Freemarker 模板中,我们可以使用转义指令自动对包含块内的所有插值应用转义:

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

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

谢谢。

4

5 回答 5

5

要详细说明 Attila 的答案:您可以使用这样的类,然后像这样包装您的模板加载器:

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]。

于 2009-11-05T07:36:58.337 回答
5

从 2.3.24 开始,每个模板都有一个关联的freemarker.core.OutputFormat对象,它指定是否以及如何转义${...}(and )。对于 HTML、XML 和 RTF 是开箱即用的,但您也可以定义自己的格式。默认情况下选定的逃脱时,您可以防止明确逃脱。#{...}OuputFormatOutputFormat${foo?no_esc}

有几种方法可以将模板与OutputFormat您想要的相关联。对于 HTML 和 XML 转义,推荐的方法是将recognize_standard_file_extensions配置设置设置为true,然后使用ftlhHTML 的ftlx文件扩展名和 XML 模板的文件扩展名。您还可以OutputFormat使用设置将 -s 与基于任意模板名称(模板路径)模式的模板相关联template_configurers。最后同样重要的是,您可以在全局范围内设置默认输出格式,例如configuration.setOutputFormat(HTMLOutputFormat.INSTANCE). 您也可以将模板顶部的输出格式覆盖为<#ftl output_format='HTML'>,尽管它应该很少使用。

相关文档页面: http: //freemarker.org/docs/dgui_misc_autoescaping.html、http : //freemarker.org/docs/pgui_config_outputformatsautoesc.html

于 2016-03-29T20:12:32.833 回答
2

如果您使用 <#include parse=false .../> 在模板中包含例如 HTML,则链接中建议的 TemplateLoaders 需要稍作调整。

此外,您需要复制 spring.ftl 并使用您自己的副本,并像 Tom 所说的那样删除顶部的 <#ftl ..> 指令。

以下效果很好,虽然有点粗糙(在 commons-io 上使用番石榴)

@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);  
   }  
} 
于 2012-02-14T22:17:33.230 回答
2

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

明显的缺点: - 第一行中的列号将被丢弃 - 如果您的模板以 <#ftl> 声明开头,则需要在其后插入 <#escape>。

于 2009-08-12T12:49:02.317 回答
1

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

于 2011-10-16T05:13:58.937 回答