逸出Freemarker的模板,我們可以使用轉義指令的逃逸自動應用到包含塊內的所有插值:默認在Freemarker的
<#escape x as x?html>
<#-- name is escaped as html -->
Hallo, ${name}
</#escape>
有沒有一種方法以編程方式達到類似的效果,定義了默認轉義應用於模板中的所有插值,包括那些外部轉義指令?
謝謝。
逸出Freemarker的模板,我們可以使用轉義指令的逃逸自動應用到包含塊內的所有插值:默認在Freemarker的
<#escape x as x?html>
<#-- name is escaped as html -->
Hallo, ${name}
</#escape>
有沒有一種方法以編程方式達到類似的效果,定義了默認轉義應用於模板中的所有插值,包括那些外部轉義指令?
謝謝。
有一個解決方案,雖然它不是微不足道的。您可以創建一個特殊的TemplateLoader來封裝其他模板加載器,並在模板源文本的序言中注入#escape x作爲x?html>,並添加爲它的結尾。
明顯的缺點: - 列數在第一行會被甩出 - 如果您的模板與< #ftl>聲明開始,你需要在它後面插入< #escape>。
爲了詳細說明阿提拉的回答是:你可以使用一個類像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]。
實際上您並不需要WrappingReader來添加換碼。你可以在任何TemplateLoader周圍創建一個裝飾器,在模板中讀入一個String,在escapes中包裝模板文本,然後返回一個讀取結果String的StringReader。要看看如何完成看看here。我發現的唯一問題是,如果你使用這種方法並從類路徑中包含spring.ftl宏,它們將會炸燬,因爲它們在頂部有一個< #ftl>聲明。但是,您可以簡單地將spring.ftl複製到您的模板路徑中,並刪除聲明(以及所有轉義指令,因爲您將默認轉義)。
如果您正在使用< #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);
}
}
由於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.html,http://freemarker.org/docs/pgui_config_outputformatsautoesc.html
彼得鏈接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
@StefanHaberl:我更新了答案 - 謝謝。 – 2013-09-27 04:41:32