3月8日博客园出现首页不显示内容的问题,是由于.Text程序没有对用户显示名称进行脚本过滤造成的。.Text中,还有不少地方存在这样的问题。实际上,每个用户输入的并且会在页面上显示的内容都要进行脚本过滤,不然难免安全隐患。
.Text中如何对用户输入的内容进行过滤的呢?主要通过EntryValidationHandler与CommentFormatHandler两个类来完成的,它们在数据被提交到数据库之前对数据进行检查与处理。
EntryValidationHandler主要是检查,发现不合法的内容就进行错误提示,不向数据库提交,但.Text的检查方法好像有点问题,从Word复制过来的html内容,比如:从VS.NET复制到Word再复制.Text中,.Text总是无法通过检查,没办法,博客园为了方便大家,只能自己写代码处理,现在只是简单过滤掉script。
CommentFormatHandler主要作用是将评论中html标记转换成文本,这样就避免了评论中的恶意内容。
显然,.Text中对恶意脚本的处理存在不足:
1、在EntryValidationHandler中,只对文章的内容进行检查,在.Text中文章用一个Entry实体类来表示,.Text寻Enrty.Body进行了检查,实际上Enry类的很多属性也要进行恶意脚本检查与过滤。
2、.Text中还有一个重要的实体类BlogConfig,BlogConfig中的很多数据是要用户去维护的,所以对BlogConfig的某些属性进行检查也是必要的,博客园出现的问题,也就是由于.Text没有这个实体类进行检查。
3、博客园中增加了高级评论功能,所以显示评论时,要允许html代码,而原来的.Text中是不允许html的(所以不必担心恶意内容),但现在博客园的程序必须对评论进行处理,实际上评论也是用Enry类表示,只要对Enry类进行处理就解决了评论的问题。
应该如何有效过滤恶意脚本?我想过三种方法:
1、当用户在表单中输入数据提交时,进行检查。但这种方法无法对Blog桌面工具发表的文章进行检查,这类文章还要单独处理。
2、在显示时进行过滤,这种很明显,既麻烦又容易出现问题,只要一处忘了进行过滤,就会前功尽弃。
3、在数据提交到数据库之前进行过滤,.Text就是采用这种方法,但不足之处是在每个数据更新操作之前,都要进行检查。
我觉得这三种方法都不是很有效的方法,好的方法应该在一个统一的地方对进行恶意内容进行过滤。为何不把目光关注到这两个实体类?只要对这两个实体类进行检查与过滤,那不就解决问题了吗?既然所有的操作都是围绕这两个实体类,只要我们对这两个实体类中的相关属性进行检查与过滤,那就不担心其他地方会出现未过滤的内容。虽然.Text有的地方显示数据时,没有访问实体类,但所有更新数据的操作都是通过实体类传递数据的。我现在想到的一种方法是在实体类相关属性的Get中进行处理,在Get返回之前,对属性值进行过滤。这是一种简单有效的方法,但不是完美的方法,我们要尽可能减少对实体类的修改。能不能用设计模式去解决这个问题,用DECORATOR模式?很多模式是针对接口与方法的,而这里的实体类是用于表示数据的,全是属性,没有方法。JGTM的文章A Taste of AOP from Solving Problems with OOP and Design Patterns 也是讨论相关问题的,文章我还没全部理解,但那也是针对在调用对象的方法之前进行附加的处理,而对属性该如何处理?
请大家提供一些好的思路,或者有什么简单的办法,请指点!
文章有不妥之处,请见谅,毕竟出于一个.NET技术水平不高的作者之手。
其他朋友的相关评论;
a.实际上可以直接利用server.htmlencode(内容)将所有的<>转换成相应的<=< >=> 然后修改的时候就可以server.HtmlDecode(内容)来下午解码就可以了。也省去了replace来替代。
不知道这样子行吗?
b.html是要显示的, 目前主要是过滤script代码。
c.我认为在Entry实体类的更新操作中进行过滤是比较好的方式。
d..
这种情况可以考虑在Get/Set方法内部返回/保存内容之前调用一个ValidateContent()虚方法(TEMPLATE METHOD),把对内容的验证逻辑潜入到已有逻辑中(并可以在子类中重载改变),或者如果对所有子类的验证逻辑都是一致的话,不实现为虚方法也可以。
BTW: 属性其实就是一对儿方法(getter/setter),没有什么本质的区别。
e.第一楼的方法看着简单,其实是把所有HTML都枪毙了,这还不如把内容都用XMP置标括起来呢。;)
f.
g.
h.
h.
i.
不过——dudu的实践精神我是十分鼓励和赞赏的!什么事情你不亲自做一下你怎么知道就不行或者不好呢?所以还是鼓励大家遇到问题的时候多动手、多动脑!GJGJ…… :)