tokenization of html
by
at 2011-08-29 22:38:50
original http://yiminghe.iteye.com/blog/1160895
html 符号解析问题
场景:
在页面上输出包含已有数据的 textarea ,一般的做法即是,将所有的数据从数据库取出后都 escapeHtml 一下:
<textarea><script>if(a&&1)alert(1);<script></textarea>
页面瞬时增大了很多,特别是对于富文本情况(包含了很多 < > &) 等,但这又是必须做的,否则会被恶意结束 textarea 标签而造成 script 注入问题,但还是存在可以进一步减少体积的余地。
规范:
查看 html 对 textarea 标签及其内容的解析规则 :实际上textarea 的内容解析规则是按照 RCDATA 类型(一系列状态),简单描述如下
1. 遇到 & ,尽力得到实体字符 代表的值
2. 遇到 < , 如果下一个字符为 / 则结束当前标签
3. 否则作为 textarea 内容
恶意结束标签主要发生在 2 ,那么我们只要打破 2 ,保证 < 和 / 不相连即可,在服务器端渲染页面事先只做一点处理,再把处理后的内容放在 textarea 中:
"<a>x</>".replace(/<\//gi,"</")
而如果允许用户输入 > 等代表实体字符的字符串,则还要进行 & 替换:
"<a>x</>".replace(/&/gi,"&")
最终页面体积也能减小不少.
其他类型:
tokenization 部分还存在其他特殊类型的解析规则,比如常见的 script ,在 xhtml 时代,推荐的写法是:
<script type="text/javascript"> /* <![CDATA[ */ // TODO /* ]]> */ </script>
这在 html 中也是支持的, cdata 的解析规则 比较简单:在遇到 ]]> 之前都算作 script 的内容,并不解析实体字符.
而 html 则是完全可以不用 cdata 这个规则的 ,script 解析本身就是一种单独规则了:
1. 类似 rcdata (因此代码中不能出现类似 "</script>",必须改做 "<\/script>"),但是不解析实体字符
2. 还识别了 <!-- ,似乎是为了兼容不支持js的远古浏览器的注释:
<script type="text/javascript"> <!-- // hide from really old browsers that noone uses anymore // TODO // --> </script>
这在现在看来则是完全不必要了。
<br><br>
<span style="color:red">
<a href="http://yiminghe.iteye.com/blog/1160895#comments" style="color:red">已有 <strong>2</strong> 人发表留言,猛击->><strong>这里</strong><<-参与讨论</a>
</span>
<br><br><br>
ITeye推荐