当前位置:首页 > 在线留言 >

Asp.net Mvc中利用ValidationAttribute实现xss过滤

作者:曲靖市宁江木业有限公司 来源:www.ynnjmy.com 发布时间:2017-09-10 09:44:11

Asp.net Mvc中利用ValidationAttribute实现xss过滤 在网站开发中,需要注意的一个问题就是防范XSS攻击,Asp.net mvc中已经自动为我们提供了这个功能。用户提交数据时时,在生成Action参数的过程中asp.net会对用户提交的数据进行验证,一旦发现提交的数据中包含了XSS攻击的代码,就会抛出异常,用户在这时候就会看到一个出错页面。这种默认的行为保证了网站的安全性,但是对于用户体验来说却不够友好,所以大多数人都希望对用户进行提示,或者对提交的数据进行过滤,移除掉XSS攻击的代码。

对于此类问题,网上有很多人问过,通过百度搜索出来的解决方法好多都只提到了“关闭页面数据验证”。确实,关闭了页面数据验证后,用户提交的任何数据都会到达服务器端的处理程序,在asp.net mvc中这一点可以通过在model的相应属性上附加AllowHtmlAttribute或者在Action上附加ValidateInputAttribute(false)来实现。但是比关闭页面数据验证更重要的一点是,关闭之后,这个数据验证和处理的重担就要由程序员来承担了。

解决这个问题最直接的方法就是在每一个要处理提交数据的Action的开始,对相应的参数进行过滤,对于XSS攻击代码的过滤,可以使用微软发布的名为AntiXss的类库,通过Nuget可以获取该类库,在我的解决方法中也是使用此类库进行过滤的。

我新建了一个Asp.net mvc项目进行演示,只有一个Controller名字为PersonController,一个Model,名字为PersonModel,PersonController中只有两个Action,全部代码如下。

复制代码

public class PersonModel

{

[AllowHtml]

//别忘了AllowHtmlAttribute,要不然提交数据就报错了

public string Name get; set;

public int Age get; set;

}

public class PersonController : Controller

{

public ActionResult Index()

return View();

public ActionResult Save(PersonModel model)

//Sanitizer为AntiXss类库提供的静态类,用于过滤XSS代码

model.Name = Sanitizer.GetSafeHtmlFragment(model.Name);

//保存到数据库中

return Content("Success");

}

复制代码

视图文件Index.cshtml内容如下

复制代码

@model AntiXss.Models.PersonModel

@

ViewBag.Title = "Index";

<h2>Index</h2>

@using (Html.BeginForm("Save","Person",FormMethod.Post))

@Html.LabelFor(model=>model.Name);

@Html.EditorFor(model=>model.Name);

<br/>

@Html.LabelFor(model=>model.Age)

@Html.EditorFor(model=>model.Age)

<input type="submit" value="submit"/>

复制代码

这样的代码无疑是可以达到我们过来XSS攻击的目的的,但是在实际项目中,Controller往往有数十个,Action的数目更是成百上千,而且ViewModel的属性又往往很多,如果我们按照上面的方式逐个Action的逐个Model的属性进行处理,代码会变得又臭又长,而且还容易遗漏。使用这种方式来进行过滤实在是一种自虐行为呀。

优秀的程序员都是懒汉,对于这种繁琐的体力劳动,一定要想方设法地避免。在asp.net mvc中,给我们提供了很多工具以实现aop编程,最常用的就是各种Filter了,所以在解决此问题时,我就想是否可以利用asp.net mvc提供的aop编程来实现XSS过滤,经过思考和翻阅蒋金楠的《ASP.NET MVC4框架揭秘》,最终找到了一种较好的解决方式,就是通过ValidationAttribute来实现XSS攻击代码过滤。

ValidationAttribute是所有验证属性的基类,RangeAttribute, RequiredAttribute, StringLengthAttribute都是它的子类,这个类的中包有一个名为IsValid的方法,来对数据进行验证,方法声明如下:

protected virtual ValidationResult IsValid(Object value, ValidationContext validationContext)

参数value即为要验证的对象,参数ValidationContext为验证上下文,此类包含了较多的信息,比较重要的有属性ObjectInstance和MemberName。

其中ValidationContext的ObjectInstance属性可获取要验证的对象,而MemberName可获取或设置要验证的成员名称。这里要进行一下解释,按照我上面的说法,value是要验证的对象,ValidationContext.ObjectInstance也是要验证的对象,难道它们二者是同一个对象么,答案是No,(不是我故意要把他们表达成一个意思,而是MSDN太坑,本段开头摘自MSDN),对于我们示例中的PersonModel类型来说,由于其是一个复杂类型,所以最终的验证会落到它的各个属性上,假如要验证属性Name,参数value即为属性Name的值,而ValidationContext.ObjectInstance则为一个PersonModel的实例,ValidationContext.MemberName的值按照MSDN的解释,应该是一个字符串“Name”;这下大家清楚二者的区别了吧。我之所以说假如要验证属性Name,专题,是因为属性Name上现在还没有任何的验证特性(AllowHtmlAttribute不是一个验证特性)。

到这里我想可能有的人已经想到我要怎么做了,在这里我获得了属性值value,也获得了包含该属性的实例ValidationContext.ObjectInstance,接下来我要做的就是将该属性值进行修改就可以了,修改属性值可以通过反射轻松实现,所以我的用于过滤XSS攻击代码的自定义验证属性就写出来了,如下

复制代码

public class AntiXssAttribute :ValidationAttribute

{

protected override ValidationResult IsValid(object value, ValidationContext validationContext)

{

//对于XSS攻击,只需要对string类型进行验证就可以了

var str = value as string;

if (!string.IsNullOrWhiteSpace(str) &&

validationContext.ObjectInstance != null && !

string.IsNullOrWhiteSpace(validationContext.MemberName))

str = Sanitizer.GetSafeHtmlFragment(str);

PropertyInfo pi = validationContext.ObjectType.GetProperty(validationContext.MemberName,

BindingFlags.Public

//由于这个类的目的并不是为了验证,所以返回验证成功

return ValidationResult.Success;

}

}

复制代码

企业建站2800元起,携手武汉肥猫科技,做一个有见地的颜值派!更多优惠请戳:神农架网站建设 http://shennongjia.45qun.com

  • 上一篇:易错域名启示录 教你如何取个好记的域名
  • 下一篇:最后一页