Spring MVC中使用自定义TemplateLoader对freemarker模板做全局html转义

freemarker作为"通用"模版引擎, 默认情况下不会对model中的值进行html转义, 然而在web项目中, 为了防止跨站脚本攻击等问题, 必须在对model中的值进行转义.  

解决办法: 

方法1. 是使用 ${x?html} 可以用于对单个值的转义

方法2. 使用<#escape x as x?html> ... </#escape> 将需要转义的html代码包起来, 这样其中所有的值都会被转义了. 

毫无疑问这两个方法都需要大量的重复操作, 如果我所有的模板都需要转义, 有没有一劳永逸的办法呢? 

方法3. 使用自定义TemplateLoader

首先我们需要实现一个TemplateLoader. 代码如下:

public class HtmlTemplateLoader implements TemplateLoader {

    

    private static final String HTML_ESCAPE_PREFIX= "<#escape x as x?html>";

    private static final String HTML_ESCAPE_SUFFIX = "</#escape>";

    

    private final TemplateLoader delegate;



    public HtmlTemplateLoader(TemplateLoader delegate) {

        this.delegate = delegate;

    }



    @Override

    public Object findTemplateSource(String name) throws IOException {

        return delegate.findTemplateSource(name);

    }



    @Override

    public long getLastModified(Object templateSource) {

        return delegate.getLastModified(templateSource);

    }



    @Override

    public Reader getReader(Object templateSource, String encoding) throws IOException {

        Reader reader = delegate.getReader(templateSource, encoding);

        String templateText = IOUtils.toString(reader);

        return new StringReader(HTML_ESCAPE_PREFIX+templateText + HTML_ESCAPE_SUFFIX);

    }



    @Override

    public void closeTemplateSource(Object templateSource) throws IOException {

        delegate.closeTemplateSource(templateSource);

    }



}

 

这里使用了一个delegate模式, 因为我们只需要对getReader()方法做小幅的更改, (其他的则委托给默认的TemplateLoader去做就可以), 实现方式很简单, 就是在读取template文件之后, 在前后套上<#escape>标签而已. 

为了和SpringMVC结合起来使用呢, 我们还需要自定义一个FreeMarkerConfigurer. 

public class CustomFreeMarkerConfigurer extends FreeMarkerConfigurer{

    

    @Override

    protected TemplateLoader getAggregateTemplateLoader(List<TemplateLoader> templateLoaders) {
return new HtmlTemplateLoader(super.getAggregateTemplateLoader(templateLoaders));
} }

然后在spring的xml配置中, 使用它来代替默认的FreeMarkerConfigurer即可.

<bean id="freemarkerConfigurer"

        class="com.ananda.oa.web.assistant.freemarker.AnandaFreeMarkerConfigurer">

<!-- 其他配置跟之前相同 -->

</bean>

你可能感兴趣的:(freemarker)