4

在 HTML 模板引擎中,默认占位符文本对 HTML 进行转义是非常好的做法,以帮助防止 XSS(跨站点脚本)攻击。是否可以在 StringTemplate 中实现这种行为?

我试图注册自定义AttributeRenderer转义 HTML,除非format"raw"

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);
    }
});

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

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;

有人可以帮忙吗?

4

2 回答 2

3

默认情况下编码没有好的解决方案。模板是通过字符串数据类型的 AttributeRenderer 传递的,并且没有上下文信息来检测它是在处理模板还是变量。因此,包括模板在内的所有字符串都是默认编码的,因为您不能为模板指定“原始”。

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

  • 降低
  • 网址编码
  • 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 具有严格的视图/模型分离,您需要在使用原始值和转义值呈现模型之前填充模型。

这两个选项都不是特别理想,但我没有看到 StringTemplate4 的任何其他替代方案。

于 2017-05-18T16:25:01.293 回答
1

答案是恢复到 StringTemplate v3。

于 2015-03-30T15:23:16.067 回答