ASP.NET MVC Anti-XSS方案

2017-01-02 19:19:14来源:作者:人点击

第七城市
1:Form提交模式
在使用Form提交时,MVC框架提供了一个默认的机制。如果数据中含有恶意字,则会自动转向出错页面。


2:Ajax+JSON提交模式。
MVC框架未提供对于Json数据的AntiXSS支持,所以必须自行实现。

Step1:定义一个Attribute[AllowHtml],如果有这个标记,则说明该属性允许Html,不需要验证。

/// <summary>
/// 用于标记某个属性是否允许html字符
/// </summary>
[AttributeUsage(AttributeTargets.Property, AllowMultiple = false, Inherited = true)]
public sealed class AllowHtmlAttribute : Attribute
{

}


Step2:元数据解析的时候,动态设定标记为AllowHtml的属性不激发验证。

public class CustomModelMetadataProvider : DataAnnotationsModelMetadataProvider
{

public CustomModelMetadataProvider()
{
}

protected override ModelMetadata CreateMetadata(IEnumerable<Attribute> attributes, Type containerType,
Func<object> modelAccessor, Type modelType, string propertyName)
{
var metadata = base.CreateMetadata(attributes, containerType, modelAccessor, modelType, propertyName);
if (containerType == null || propertyName == null)
return metadata;

foreach (Attribute attr in attributes)
{
if (attr is AllowHtmlAttribute)
{
metadata.RequestValidationEnabled = false;
break;
}
}
}
}


Step3:实现自定义ModerBinder,拦截所有的json数据,进行anti-xss验证。

/// <summary>
/// 检测Json数据中含有恶意字符,抛出HttpRequestValidationException
/// </summary>
public class AntiXssModelBinder : DefaultModelBinder
{
protected override bool OnPropertyValidating(ControllerContext controllerContext, ModelBindingContext bindingContext, System.ComponentModel.PropertyDescriptor propertyDescriptor, object value)
{
if (controllerContext.HttpContext.Request.ContentType.StartsWith("application/json", StringComparison.OrdinalIgnoreCase))
{
int index;

if (controllerContext.Controller.ValidateRequest
&& bindingContext.PropertyMetadata[propertyDescriptor.Name].RequestValidationEnabled)
{
if (value is string)
{
if (AntiXssStringHelper.IsDangerousString(value.ToString(), out index))
{
throw new HttpRequestValidationException("Dangerous Input Detected");
}
}
else if (value is IEnumerable)
{
// 字符串数组或者集合,或者Dictionary<string, string>
// Dictionary的Key, Value会ToString后一起验证
foreach (object obj in value as IEnumerable)
{
if (obj != null)
{
if (AntiXssStringHelper.IsDangerousString(obj.ToString(), out index))
{
throw new HttpRequestValidationException("Dangerous Input Detected");
}
}
}
}
}
}

return base.OnPropertyValidating(controllerContext, bindingContext, propertyDescriptor, value);
}
}

/// <summary>
/// 检测绑定的单值字符串是否包含恶意字符
/// </summary>
public class AntiXssRawModelBinder : StringTrimModelBinder
{
public override object BindModel(ControllerContext controllerContext, ModelBindingContext bindingContext)
{
var value = base.BindModel(controllerContext, bindingContext);
if (value is string)
{
var result = (value as string).Trim();
int index;
if (AntiXssStringHelper.IsDangerousString(value.ToString(), out index))
{
throw new HttpRequestValidationException("Dangerous Input Detected");
}
}

return value;
}
}
}


Step4:在Web站点启动的时候,配置MVC框架

RouteTableRegister.RegisterRoutes(_routes);

BundleConfig.RegisterBundles(BundleTable.Bundles);

ModelMetadataProviders.Current = new CustomModelMetadataProvider();
ModelBinders.Binders.DefaultBinder = new AntiXssModelBinder();


举例:

[Required]
[AllowHtml]
public string UserName{get;set;}
[Required]
public string Password{get;set;}
注意:这时通过JSON传过来的数据Password就会报错,而UserName则不会。


如果Ajax传入的JSON是封装好的对象,最好也要经过封装,以下为例:

public ActionResult Login(LoginModel model,[ModelBinder(typeof(AntiXssRawModelBinder))])
{
}


//AntiXssRawModelBinder核心代码
/// <summary>
/// 检测绑定的单值字符串是否包含恶意字符
/// </summary>
public class AntiXssRawModelBinder : StringTrimModelBinder
{
public override object BindModel(ControllerContext controllerContext, ModelBindingContext bindingContext)
{
var value = base.BindModel(controllerContext, bindingContext);
if (value is string)
{
var result = (value as string).Trim();
int index;
if (AntiXssStringHelper.IsDangerousString(value.ToString(), out index))
{
throw new HttpRequestValidationException("Dangerous Input Detected");
}
}

return value;
}
}



如果某些参数需要支持部分HTML代码,可以采取先将该参数设置为[AllowHTML],值传到Action时,再进行手动过滤,或者 使用AntiXSS库进行编码(微软提供的AntiXSSLibrary类库)。

整理网络文章,如有错误,敬请指正,非常感谢!
第七城市

最新文章

123

最新摄影

微信扫一扫

第七城市微信公众平台