一个较完整的关键字过滤解决方案(中)
ar handlerType = context.Handler.GetType(); var filter = ((FilterForbiddenWordAttribute[]) handlerType.GetCustomAttributes( typeof(FilterForbiddenWordAttribute), true)).FirstOrDefault(); ProcessCollection(context.Request.QueryString, filter); ProcessCollection(context.Request.Form, filter); } private static void ProcessCollection( NameValueCollection collection, FilterForbiddenWordAttribute filter) { var copy = new NameValueCollection(); foreach (string key in collection.AllKeys) { var filterType = (filter == null) ? FilterForbiddenWordType.Normal : filter.GetFilterType(key); Array.ForEach( collection.GetValues(key), v => copy.Add(key, ForbiddenWord.Filter(v, filterType))); } ... } } 修改示例。例如我们在页面上放置两个文本框txtPassword和txtNormal:
点击,效果不言而喻: 公布答案:因为我们需要等到确认了HttpHandler类型才能获得 FilterForbiddenWordAttribute标记信息,所以这次更新的关键是我们必须推迟进行过滤的 时机。推迟到哪个阶段?自然是能够确定HttpHandler类型的最早时机, PostMapRequestHandler。我们通过反射来获取Handler类型上的 FilterForbiddenWordAttribute子类的信息,作为Filter传入带有额外参数的 ProcessCollection方法中。ProcessCollection方法内部会调用根据filter参数来确定某个 key的过滤方式:正常(当作纯文本进行过滤)、忽略(不过滤)、JSON(只过滤JSON内元素 的值)以及HTML(忽视tag和attribute,并考虑文字内的HTML Encode)。其余不变。 顺便说一句,以上代码其实只是为了写这些内容而在10分钟内写好的,不考虑性能、缓存 、同步、边界等情况——因为我相信看了下面的文字您一定会抛弃这种做法。 继续改进 上面的做法(相对使用命名约定的方式)改进了什么地方?很简单,之前提到的命名约定 的缺点就是上述做法的优点: 不同Page(Http Handler)可以自行指定字段所需要的过滤逻辑。 无需前端改名,只需后端标记。 避免复杂的命名约定,使多种横切型的过滤功能可以轻易共存。 真是美妙地嗷嗷的,但是有没有朋友看出问题来?我提示一下:GetFilterType方法中使 用了一个常量字符串txtPassword。 估计有朋友会问:“咦,这有什么问题?”粗看似乎没有,不过老赵看到代码中出现常量 总是要警惕一番(自觉是个好喜欢):为啥要是txtPassword而不是txtPassWord(一个常见 的拼写错误)?为啥代码中用0而不用-1?这里的问题倒不是说一个常量在代码中到处使用时 最好使用一个const——不不,是readonly字段来代替(为啥用const不太好?)。而是…… 再提示一下,如果某人将页面上的txtName文本框改为txtUserName那会出现何种情况? 嗯嗯,那么Attribute中的GetFilterType方法当然还是在判断一个key是否由txtName结尾 ,而我们修改后的页面中Post内容中已经变成了txtUserName,咋整?但是可悲的是,我们尊 敬的Attribute,就算你拿刀威胁 |
凌众科技专业提供服务器租用、服务器托管、企业邮局、虚拟主机等服务,公司网站:http://www.lingzhong.cn 为了给广大客户了解更多的技术信息,本技术文章收集来源于网络,凌众科技尊重文章作者的版权,如果有涉及你的版权有必要删除你的文章,请和我们联系。以上信息与文章正文是不可分割的一部分,如果您要转载本文章,请保留以上信息,谢谢! |