text/type text templatee 用js写入html的,但在输出时 {$ID}不显示

javascript 模板引擎artTemplate - 吕滔博客
自己选择的路,跪着也要把它走完
栏目分类:35个
发布文章:1081篇
用户评论:573条
: 这是13年淘宝dba分享的一片文章,网上应该还有,我拿过来还没有...
: 而net.ipv4.tcp_mem则是配置tcp的内存大小,其单...
: 我这个站不是java写的哟~~~这是typecho开源博客程序改...
: 可以使用nginx反向代理后台的这个5000端口。
: 博主的java站好快啊
: java站这么快,厉害
: psdash可以部署到nginx上吗?
: 很实用的PHP代码块!!!
: 把 .dll 发出来让我试试啊
: 这个挺不错的
: 怎么解密????
: 现在很多用畅言或多说的,改个JS就完事了,还方便,哈哈。我是折腾...
: 谢谢博主分享,代码用上了,原生评论折腾的有点烦了
: 额,毛毛雨而已啦,您这么说,,,,,这就尴尬了...
: 懂PHP的人都挺厉害的
: 好东西,先收藏着。
: 不是,是用的typecho博客程序。
: 可以用,谢谢时间: &|& 来源:
Velocity为我们提供了EscapeHtmlReference
event handler用于在引用变量值输出之前进行HTML转义处理,但是这个HTML转义功能需要通过eventhandler.escape.html.match=//配置指定变量前缀来进行,特别对于有的变量需要转义,有的变量不需要转义的情况下非常的不方便,深受之苦;因此我决定改造扩展Velocity的语法:让 $[!]{ param } 默认转义输出,增加 $#{ param } 语法支持原样输出。
一直以来在项目中使用Apache Velocity模板引擎作为视图层输出,为了解决XSS漏洞,需要对输出到页面的内容进行HTML转义,我一般采用2种方式实现:
使用过滤器&Filter,在其中进行&HttpServletRequestWrapper&的&getParameter( )等方法重载,在底层进行HTML转义,然后页面直接输出;这种方式很轻松很直接,业务代码不需要修改就完成了所有的转义工作;但是也带来了问题:修改了用户的原始输入数据,如果需要用到用户的原始输入数据,又得反转义回去,很麻烦。
在页面上使用 velocity-tools 的 $esc.html( ) 进行手工转义:$esc.html($task.content);这种方式工作量比较大,需要在转义的变量上增加&$esc.html(),很容易遗漏。
那有没有别的方法来解决呢?
后来我发现&Velocity 为我们提供了EscapeHtmlReference &event handler 用于在引用变量值输出之前进行HTML转义处理,但是这个HTML转义功能需要通过eventhandler.escape.html.match=//配置指定变量前缀来进行,特别对于有的变量需要转义,有的变量不需要转义的情况下非常的不方便;在用了一段时间后,感觉很麻烦,污染变量命名,不爽;
正巧这段时间也使用了 artTemplate.js 的前端模板引擎,发现这个模板引擎提供了2种变量输出方式:&%= param %& 和 &%== param %&,其中 &%= param %& 是默认的常用输出方式(会对变量值中的HTML字符进行转义输出),&%== param %& 则是原样输出(不进行任何转义);感觉这样的方式非常的好,即满足了大部分的转义输出,也满足了小部分的非转义输出,而且不用对业务代码进行修改,而是由模板引擎提供不同的输出方法。
那能否修改 Velocity 的语法,也支持一种非转义输出呢?这样不就完美解决这个问题了吗?
$[ ! ][ { ] param [ } ] 是 Velocity 的默认引用定义和输出语法,为了自定义的语法简单易用,想采用 $#{ ... } 语法格式,这样和原来的语法只有一个字的差别:! -& #&
//&默认转义输出
$task.content
${task.content}
$!task.content
$!{task.content}
//&原样不转义输出
$#task.content
$#{task.content}
于是我开始研究 Velocity 的语法解析代码,Velocity 采用 AST 语法树进行模板的语法解析的,所有的语法定义在 Parser.jjt 文件中,然后使用JAVACC 编译Parser.jjt文件生成语法解析代码(ASTAddNode,ASTEQNode, ASTReference,&ASTSetDirective等等),$[ ! ][ { ] ... [ } ] 语法Velocity定义为 Reference,因此 ASTReference.java 就是用来处理&Reference&的。&
在 Parser.jjt 文件的 730 行定义了这样的语法配置:
&DOLLARBANG:&("\\")*&"$"&("\\")*&"!"&
这段语法是用来支持 $! 的,如果我把最后的 "!" 变成 ("!"|"#") 不就支持 $# 了嘛,呵呵,修改之(当然其它的语法定义也必须都看一遍):
&DOLLARBANG:&("\\")*&"$"&("\\")*&("!"|"#")&
发现在 ASTReference.java 文件的&getRoot() 方法中进行了 $! 和 $!{ 的处理:
if&(t.image.startsWith("$!"))&{
&&&&referenceType&=&QUIET_REFERENCE;
&&&&&*&&only&if&we&aren't&escaped&do&we&want&to&null&the&output
&&&&if&(!escaped)&nullString&=&"";
&&&&if&(t.image.startsWith("$!{"))&{
&*&&ex&:&$!{provider.Title}
return&t.next.
&&&&}&else&{
&*&&ex&:&$!provider.Title
return&t.image.substring(2);
在有了上面的了解后,修改Velocity的Reference 语法规则就简单了,迅速修改 Parser.jjt 文件,然后使用 JAVACC(我使用javacc-eclipse插件) 编译Parser.jjt,生成了和Velocity src 下源码一样的AST代码结构,由于我修改的仅仅是 Reference 的语法,因此生成的代码文件中我只保留了&ParserTokenManager.java&文件(用于替换src的该文件,这个文件代码很多,又没有发现可以上传附件的地方,因此代码就不贴出了),其它的文件使用原始 src 下的文件(注意:原始src下的AST文件大部分被后期手工修改完善,因此不能完全使用新编译生成的AST代码文件)。
同时对原始的 ASTReference.java 的 getRoot() 方法中的代码进行扩充,支持 $# 的处理:
if&(t.image.startsWith("$!")&||&t.image.startsWith("$#"))&{
referenceType&=&QUIET_REFERENCE;
&*&&only&if&we&aren't&escaped&do&we&want&to&null&the&output
if&(!escaped)&nullString&=&"";
if&(t.image.startsWith("$!{")&||&t.image.startsWith("$#{"))
&*&&ex&:&$!{provider.Title}&OR&$#{provider.Title}
return&t.next.
&*&&ex&:&$!provider.Title&OR&$#provider.Title
return&t.image.substring(2);
然后测试,一切OK,这样 Velocity 就多了一个语法:$#[ { ] ... [ } ] 支持。
哦,还没完呢,呵呵,此时 $#{} 仅仅和 $!{} 一样,下面开始对这2个命令进行处理:$!{} -- 转义输出, $#{} -- 不转义输出:
为了不修改原始核心代码,方便扩展,这里采用扩展 Velocity 提供的&ReferenceInsertionEventHandler 接口实现进行(类似EscapeHtmlReference),直接上代码和配置:
import&org.apache.velocity.app.event.ReferenceInsertionEventH
import&org.apache.velocity.runtime.RuntimeS
import&org.apache.velocity.util.RuntimeServicesA
&*&HTML转义输出
public&class&VelocityEscapeHtmlOutput&
implements&ReferenceInsertionEventHandler,&RuntimeServicesAware
private&RuntimeServices&rs&=&
public&Object&referenceInsert(String&reference,&Object&value)&
&&&&&&&//&呵呵,这里...&凡是以&$#开头的reference,其值直接返回(^_^)
if(reference.startsWith("$#"))&{
//&其它默认转义
return&escapeHtml(value);
public&void&setRuntimeServices(RuntimeServices&rs)&
this.rs&=&
protected&RuntimeServices&getRuntimeServices()
return&this.
&*&转义HTML字符串
&*&@param&str
&*&@return
private&static&Object&escapeHtml(Object&value)
if(value&==&null)
if(!(value&instanceof&String))
String&str&=&value.toString();
StringBuilder&sb&=&new&StringBuilder(str.length()&+&30);
for(int&i&=&0,&len&=&str.length();&i&&&&i++)
char&c&=&str.charAt(i);
//&去除不可见字符
if((int)c&&&32)
sb.append("<");
sb.append(">");
sb.append("&");
sb.append(""");
case&'\'':
sb.append("'");
sb.append("/");
sb.append(c);
return&sb.toString();
Velocity 提供的EventHandler接口需要在 velocity.properties中进行配置才能生效:
eventhandler.referenceinsertion.class&=&com.xxx.VelocityEscapeHtmlOutput
到此为止,就完成了对 Velocity 的 Reference 语法改造了!尽情享用吧!标签: , , ,
赞助商广告():
如果你月薪不足20K,不妨
如果你有1~3年前端开发经验,不妨
听说、你想学JS?不妨
发表评论(目前12 条评论)
热门总排行1 &!DOCTYPE html&
&META http-equiv=Content-Type content="text/ charset=utf-8"&
&title&关于HTML编码 - by 杨元&/title&
&h1&关于HTML编码&/h1&
&!--基础html框架--&
&th&姓名&/th&
&th&性别&/th&
&th&年龄&/th&
&th&个人主页&/th&
&tbody id="tableList"&
&!--插件引用--&
&script type="text/javascript" src="script/jquery.js"&&/script&
&script type="text/javascript" src="script/handlebars-1.0.0.beta.6.js"&&/script&
&!--Handlebars.js模版--&
&!--Handlebars.js模版放在script标签中,保留了html原有层次结构,模版中要写一些操作语句--&
&!--id可以用来唯一确定一个模版,type是模版固定的写法--&
&script id="table-template" type="text/x-handlebars-template"&
{{#each student}}
&td&{{name}}&/td&
&td&{{sex}}&/td&
&td&{{age}}&/td&
{{#compare age 20}}
&td&{{homePage}}&/td&
&td&{{{homePage}}}&/td&
{{/compare}}
&!--进行数据处理、html构造--&
&script type="text/javascript"&
$(document).ready(function() {
//模拟的json对象
var data = {
"student": [
"name": "张三",
"sex": "0",
"age": 18,
"homePage":"&a href='javascript:void(0);'&张三的个人主页&/a&"
"name": "李四",
"sex": "0",
"age": 22,
"homePage":"&a href='javascript:void(0);'&李四的个人主页&/a&"
"name": "妞妞",
"sex": "1",
"age": 19,
"homePage":"&a href='javascript:void(0);'&妞妞的个人主页&/a&"
//注册一个Handlebars模版,通过id找到某一个模版,获取模版的html框架
//$("#table-template").html()是jquery的语法,不懂的童鞋请恶补。。。
var myTemplate = pile($("#table-template").html());
//注册一个比较数字大小的Helper,有options参数,块级Helper
Handlebars.registerHelper("compare",function(v1,v2,options){
//判断v1是否比v2大
if(v1&v2){
//继续执行
return options.fn(this);
//执行else部分
return options.inverse(this);
//将json对象用刚刚注册的Handlebars模版封装,得到最终的html,插入到基础table中。
$('#tableList').html(myTemplate(data));
94 &/html&
&&&& 通过{{}}取出来的内容,都会经过编码,也就是说,如果取出的内容中包含html标签,会被转码成纯文本,不会被当成html解析,实际上就是做了类似这样的操作:把&用&替代。
&&&& 这样做是很好的,既可以显示html代码,又可以避免xss注入。这个功能在做代码展示的时候是非常有用的。
&&&& 但是有时候我们可能需要解析html,不要转码,很简单,把{{}}换成{{{}}}就可以啦。
&&&& 本例中,年龄大于20的童鞋个人主页被编码,直接展示出来;而年龄小于20的童鞋,个人主页被当成html解析,显示的是一个超链接。
阅读(...) 评论()2016年2月 总版技术专家分月排行榜第二2014年2月 总版技术专家分月排行榜第二2013年4月 总版技术专家分月排行榜第二
2016年10月优秀小版主
2016年8月优秀小版主2016年7月优秀小版主优秀小版主2015年7月优秀小版主2015年9月优秀小版主2015年5月优秀小版主2014年11月论坛优秀版主
2016年2月 总版技术专家分月排行榜第二2014年2月 总版技术专家分月排行榜第二2013年4月 总版技术专家分月排行榜第二
2016年10月优秀小版主
2016年8月优秀小版主2016年7月优秀小版主优秀小版主2015年7月优秀小版主2015年9月优秀小版主2015年5月优秀小版主2014年11月论坛优秀版主
2016年2月 总版技术专家分月排行榜第二2014年2月 总版技术专家分月排行榜第二2013年4月 总版技术专家分月排行榜第二
2016年10月优秀小版主
2016年8月优秀小版主2016年7月优秀小版主优秀小版主2015年7月优秀小版主2015年9月优秀小版主2015年5月优秀小版主2014年11月论坛优秀版主
2016年2月 总版技术专家分月排行榜第二2014年2月 总版技术专家分月排行榜第二2013年4月 总版技术专家分月排行榜第二
2016年10月优秀小版主
2016年8月优秀小版主2016年7月优秀小版主优秀小版主2015年7月优秀小版主2015年9月优秀小版主2015年5月优秀小版主2014年11月论坛优秀版主
2016年2月 总版技术专家分月排行榜第二2014年2月 总版技术专家分月排行榜第二2013年4月 总版技术专家分月排行榜第二
2016年10月优秀小版主
2016年8月优秀小版主2016年7月优秀小版主优秀小版主2015年7月优秀小版主2015年9月优秀小版主2015年5月优秀小版主2014年11月论坛优秀版主
本帖子已过去太久远了,不再提供回复功能。}

我要回帖

更多关于 template.js 输出html 的文章

更多推荐

版权声明:文章内容来源于网络,版权归原作者所有,如有侵权请点击这里与我们联系,我们将及时删除。

点击添加站长微信