如何在StringTemplate中默认转义HTML?

时间:2014-05-24 07:11:01

标签: java stringtemplate stringtemplate-4

HTML模板引擎中的默认占位符文本是HTML-escape,这有助于防止XSS(跨站点脚本)攻击。是否可以在StringTemplate中实现此行为?

我尝试注册自定义AttributeRenderer,除非format"raw",否则会转义HTML:

stg.registerRenderer(String.class, new AttributeRenderer() {
    @Override
    public String toString(Object o, String format, Locale locale)  {
        String s = (String)o;
        return Objects.equals(format, "raw") ? s : StringEscapeUtils.escapeHtml4(s);
    }
});

但它失败了,因为在这种情况下,StringTemlate不仅会转义占位符文本,还会转义模板文本本身。例如这个模板:

example(title, content) ::= <<
    <html>
        <head>
            <title>$title$</title>
        </head>
        <body>
            $content; format = "raw"$
        </body>
    </html>
>>

呈现为:

&lt;html&gt;
    &lt;head&gt;
        &lt;title&gt;Example Title&lt;/title&gt;
    &lt;/head&gt;
    &lt;body&gt;
        <p>Not escaped because of <code>format = "raw"</code>.</p>
    &lt;/body&gt;
&lt;/html&gt;

有人可以帮忙吗?

2 个答案:

答案 0 :(得分:1)

默认编码没有好的解决方案。模板通过AttributeRenderer传递给字符串数据类型,并且没有上下文信息来检测它是否正在处理模板或变量。因此,所有字符串(包括模板)都是默认编码的,因为您无法为模板指定“raw”。

另一种解决方案是在需要编码的变量中使用format="xml-encode"。内置StringRenderer支持多种格式:

  • URL编码
  • XML编码

所以你的例子是:

example(title, content) ::= <<
    <html>
        <head>
            <title>$title; format="xml-encode"$</title>
        </head>
        <body>
            $content$
        </body>
    </html>
>>

为了默认编码 ,您的选项有限。替代方案是:

  1. 为变量使用自定义数据类型(不是String),因此您可以为自定义数据类型注册HtmlEscapeStringRenderer。如果将复杂对象用作已使用标准字符串的变量,则很难。
  2. 手动将原始变量和转义变量添加到模型中,例如添加title(转义)和title_raw(原始)。在这种情况下,您不需要自定义AttributeRenderer。 StringTemplate具有严格的视图/模型分离,您需要在使用原始值和转义值呈现模型之前填充模型。
  3. 这两个选项都不是特别理想,但我没有看到StringTemplate4的任何其他选项。

答案 1 :(得分:0)

答案是恢复为StringTemplate v3。