阿不

潜水

  博客园 :: 首页 :: 博问 :: 闪存 :: 新随笔 :: 联系 :: 订阅 订阅 :: 管理 ::
  212 随笔 :: 0 文章 :: 3070 评论 :: 75 引用

几天前,同事浪子在用VS2010创建MVC站点时,发现里面的页面模板中大量使用了一种新的模板语法:<%: %> ,由于之前他比较少使用ASP.NET MVC,还以为是MVC里面新增的一种模板语法,而我很早就开始使用MVC工程,但也从来没有见过此种语法。于我们共同断定这可能是ASP.NET4.0中新出的一种模板语法。果然,我们在ASP.NET 4.0白皮书上找到了答案:这是用于替代<%= %>而推出的一种新的页面文件输出语法。

在白皮书中指出,一些站点,特别是ASP.NET MVC推出以后,越来越多的开发人员,选择在页面中使用<%= %>来输出字符串文本,而不是使用Server Control。这样做本身没有任何问题,也会让页面模板更为简洁,但是这样做却有可能带来安全性的问题:如果使用<%= %> 输出来自用户的输入的内容,由于<%= %> 语法没有进行HTML Encode处理,而大多数开发人员一般都不太注意自己对输出文本进行HTML Encode(我就是其中一个),这样就有可能就会带来XSS的安全性问题。因此,在一些需要显示用户输入内容时,不管使用Response.Write,还是使用<%= %>(事实上<%= %>的效果等同于Response.Write,关于更多的模板语法请参考:http://quickstarts.asp.net/QuickStartv20/aspnet/doc/pages/syntax.aspx),我们的最佳实践应该都是需要先调用一下HttpUtility.HtmlEncode对文本进行一次Html编码,以保证输出安全。这样做还是稍微有一点点的麻烦,于是<%: %> 就出现了。使用<%: %> 的效果等同于我们调用了HtmlEncode以后,再使用<%=%>,实际上就是在保证安全的同时提高生产力。

我们在VS2010中创建的MVC站点,在LogOnUserControl.ascx文件中有这么一段代码:
 
<%: Html.ActionLink("Log On", "LogOn", "Account") %> 
它编译的结果如下:
__w.Write(HttpUtility.HtmlEncode(base.Html.ActionLink("Log On", "LogOn", "Account"))); 
 
这个新的语法原理本身就是这么简单。<%:%>会帮我们进行一次HtmlEncode,但是在一些情况下,我们不希望输出的文本被自动HtmlEncode;或者我们要输出的内容本身已经做过一次HtmlEncode,而且在项目我们希望统一使用<%:%>,那么再使用这个语法将会对文本进行二次编码。在这种情况下,ASP.NET 4.0中,还增加了IHtmlString接口,只要你要输出的实例实现了这个接口,HttpUtility.HtmlEncode这个方法将不会对IHtmlString的接口进行Encode,对应的HtmlEncode方法的实现如下:
public static string HtmlEncode(object value)
{
    if (value == null)
    {
        return null;
    }
    IHtmlString str = value as IHtmlString;
    if (str != null)
    {
        return str.ToHtmlString();
    }
    return HtmlEncode(Convert.ToString(value, CultureInfo.CurrentCulture));
}
 
在ASP.NET 4.0,IHtmlString的默认实现是:HtmlString,如下输出代码将不会进行HtmlEncode:
<%: new HtmlString("<strong>HTML that is not encoded</strong>") %> 
 

在MVC 2中,我们发现HtmlHelper原来返回的字符串,改为返回MvcHtmlString(由于MVC2的程序集并不直接使用ASP.NET4.0,因此它通过动态类的方式来实现IHtmlString接口),就是这个原因,不希望<%:%>对MVC输出的Html标签进行Html Encode,否则在ASP.NET 4.0可使用<%:%>将无法正常工作。

这里还要提一点,使用这个语法,不完全保证页面的没有XSS漏洞,例如当用户提交的内容中,使用了不带引号的属性值引用Html标签,一样可能会受到影响。另外,这个语法不进行javascript编码。

posted on 2010-05-29 21:19 阿不 阅读(...) 评论(...) 编辑 收藏