开发中我们往往需要给用户输入做一些特殊的过滤,主要的是防止xss攻击,至于一般的,有MaxLengthAttribute PhoneAttribute RegularExpressionAttribute等。
MaxLengthAttribute 类 (System.ComponentModel.DataAnnotations) | Microsoft Docs
上面是校验是否通过,我们这次做一个替换的,主要目的是防止xss工具,原理是比如在用户的输入字段中包裹一些js或者引入外部js等然后浏览器访问了,就可以执行这个脚本。
定义一个过滤器给模型用,主要是标注下哪些模型是使用富文本过滤的,毕竟我的思路是普通的字符串直接替换<>符号,至于富文本则有其他的规则。
public class EditHtmlAttribute : Attribute
{
public EditHtmlAttribute() { }
}
定义一个过滤器:
/// <summary>
/// XSS工具过滤
/// </summary>
public class XSSAttribute : ActionFilterAttribute
{
/// <summary>
///
/// </summary>
/// <param name="context"></param>
public override void OnActionExecuting(ActionExecutingContext context)
{
//post的xss过滤如何行驶?
//获取Action参数集合
var ps = context.ActionDescriptor.Parameters;
//遍历参数集合
foreach (var p in ps)
{
if (context.ActionArguments[p.Name] != null)
{
//当参数等于字符串
if (p.ParameterType.Equals(typeof(string)))
{
context.ActionArguments[p.Name] = StringFilter(context.ActionArguments[p.Name].ToString());
}
else if (p.ParameterType.IsClass)//当参数等于类
{
ModelFieldFilter(p.Name, p.ParameterType, context.ActionArguments[p.Name]);
}
}
}
base.OnActionExecuting(context);
}
/// <summary>
/// 遍历修改类的字符串属性
/// </summary>
/// <param name="key">类名</param>
/// <param name="t">数据类型</param>
/// <param name="obj">对象</param>
/// <returns></returns>
private object ModelFieldFilter(string key, Type t, object obj)
{
//获取类的属性集合
var ats = t.GetCustomAttributes(typeof(XSSAttribute), false);
if (obj != null)
{
//获取类的属性集合
var pps = t.GetProperties();
foreach (var pp in pps)
{
if (pp.GetValue(obj) != null)
{
//当属性等于字符串
if (pp.PropertyType.Equals(typeof(string)))
{
//pp.CustomAttributes.Contains();
var find = false;
if (pp.CustomAttributes.Count() > 0)
{
foreach (var ca in pp.CustomAttributes)
{
//是否标注了富文本
if (ca.AttributeType.Name == nameof(EditHtmlAttribute))
{
find = true;
break;
}
//可以扩展是否忽略校验
}
}
if (!find)
{
string value = pp.GetValue(obj).ToString();
pp.SetValue(obj, StringFilter(value));
}
else
{
string value = pp.GetValue(obj).ToString();
pp.SetValue(obj, HtmlFilter(value));
}
}
else if (pp.PropertyType.IsClass)//当属性等于类进行递归
{
pp.SetValue(obj, ModelFieldFilter(pp.Name, pp.PropertyType, pp.GetValue(obj)));
}
}
}
}
return obj;
}
/// <summary>
/// 基本字符串的过滤器
/// </summary>
/// <param name="val"></param>
/// <returns></returns>
private string StringFilter(string val)
{
if (!String.IsNullOrEmpty(val))
{
//这里填写普通字符串的过滤规则
return val.Replace("<", "<").Replace(">",">");
}
return val;
}
/// <summary>
/// 富文本的过滤器
/// </summary>
/// <param name="val"></param>
/// <returns></returns>
private string HtmlFilter(string val)
{
if (!String.IsNullOrEmpty(val))
{
//这里填写关于富文本的自定义过滤规则
return val.Replace("<script", "<");
}
return val;
}
}
接下来就是测试一下了。
/// <summary>
/// 验证html关键替换
/// </summary>
/// <param name="name"></param>
/// <param name="url"></param>
/// <returns></returns>
[HttpPost]
[XSSAttribute]//标注使用xss替换校验
public string PostUrl(ModelItem input)
{
return Newtonsoft.Json.JsonConvert.SerializeObject(input);
}
ModelItem的模型如下:
public class ModelItem
{
/// <summary>
/// 其他参数
/// </summary>
public int Age { get; set; }
/// <summary>
/// 一般字符串内容
/// </summary>
public string Str { get; set; }
/// <summary>
/// 富文本内容
/// </summary>
[EditHtmlAttribute]
public string Html { get; set; }
}
然后运行项目测试下!