Asp.net mvc 如何为.net核心mvc应用程序集中防止脚本注入

Asp.net mvc 如何为.net核心mvc应用程序集中防止脚本注入,asp.net-mvc,validation,asp.net-core,xss,Asp.net Mvc,Validation,Asp.net Core,Xss,我只需要一些关于实现逻辑的意见,以便集中检查输入中是否没有添加脚本 我计划使用antiXSS(Sanitizer.getSafeThmlFragment(“value”))并检查输出是否为null,这意味着它可能包含脚本并处理错误。 我可以想出一个逻辑来检查模型属性并检查值,如果有任何可疑的地方就会抛出错误 我想知道是否有更好的方法来一次性处理所有输入字段的注入,而不是为每个字段添加验证 假设我有这样一个模型: public class Login { public string Emai

我只需要一些关于实现逻辑的意见,以便集中检查输入中是否没有添加脚本

我计划使用antiXSS(Sanitizer.getSafeThmlFragment(“value”))并检查输出是否为null,这意味着它可能包含脚本并处理错误。 我可以想出一个逻辑来检查模型属性并检查值,如果有任何可疑的地方就会抛出错误

我想知道是否有更好的方法来一次性处理所有输入字段的注入,而不是为每个字段添加验证

假设我有这样一个模型:

public class Login {
   public string Email {get; set;}
   public string Password {get; set;}
}
我是否可以在点击操作之前添加一些过滤来检查非输入是否包含任何脚本,而不是在模型或验证表达式中添加一些属性,然后对每个字段单独进行html编码,然后抛出错误


我希望在顶部有一些非常重要的内容,这样我就不会遍历每个操作或模型并进行一些更改。

我使用了筛选操作并添加了这样的代码来检查请求中任何模型的字符串类型并对其进行编码。它对我们来说非常好

public static class HttpEncode
{
    public static void ParseProperties(this object model)
    {
        if (model == null) return;

        if (IsPropertyArrayOrList(model.GetType()))
        {
            ParsePropertiesOfList(model);
        }
        else
        {
            GetAllProperties(model).ForEach(t => EncodeField(t, model));
        }
    }

    private static void ParsePropertiesOfList(object model)
    {
        foreach (var item in (IEnumerable) model)
        {
            ParseProperties(item);
        }
    }

    private static List<PropertyInfo> GetAllProperties(object value) => value?.GetType()?.GetProperties()?.ToList();

    private static void EncodeField(PropertyInfo p, object arg)
    {
        try
        {
            if (p.GetIndexParameters().Length != 0 || p.GetValue(arg) == null)
                return;

            if (IsUserDefinedClass(p.PropertyType) && p.CanWrite)
            {
                ParseProperties(p.GetValue(arg));
            }
            else if (IsPropertyArrayOrList(p.PropertyType) && p.CanWrite)
            {
                ParseArrayOrListProperty(p, arg);
            }
            else if (p.PropertyType == typeof(string) && p.CanWrite)
            {
                var encodedValue = HtmlEncode(p.GetValue(arg)?.ToString());
                SetPropertyValue(p, arg, encodedValue);
            }
        }
        catch (Exception ex)
        {
            // ignored
        }
    }

    private static void ParseArrayOrListProperty(PropertyInfo p, object arg)
    {
        if (p.GetValue(arg) is string[] || p.GetValue(arg) is List<string>)
        {
            SetPropertyValueOfStaringArrayType(p, arg);
        }
        else
        {
            ParsePropertiesOfList(p.GetValue(arg));
        }
    }

    private static void SetPropertyValueOfStaringArrayType(PropertyInfo propertyInfo, object arg)
    {
        if (propertyInfo.GetValue(arg) is string[] stringValue)
        {
            var result = new List<string>();
            stringValue.ToList().ForEach(l => result.Add(HtmlEncode(l)));
            SetPropertyValue(propertyInfo, arg, result.Any() ? result.ToArray() : null);
        }
        else if (propertyInfo.GetValue(arg) is List<string> listValue)
        {
            var result = new List<string>();
            listValue.ForEach(l => result.Add(HtmlEncode(l)));
            SetPropertyValue(propertyInfo, arg, result.Any() ? result : null);
        }
    }

    private static bool IsUserDefinedClass(Type type) =>
        type.IsClass &&
        !type.FullName.StartsWith("System.");

    private static bool IsPropertyArrayOrList(Type type) =>
        type.IsArray && type.GetElementType() == typeof(string) ||
        (type != typeof(string) && type.GetInterface(typeof(IEnumerable<>).FullName) != null);

    private static void SetPropertyValue(PropertyInfo propertyInfo, object allValue, object value)
    {
        propertyInfo.SetValue(allValue, value);
    }

    private static string HtmlEncode(string value) => HttpUtility.HtmlEncode(value);

}

   public class EncodeInputsActionFilter : IAsyncActionFilter
{
    public async Task OnActionExecutionAsync(
        ActionExecutingContext context,
        ActionExecutionDelegate next)
    {
        ProcessHtmlEncoding(context);
        var resultContext = await next();
        // do something after the action executes; resultContext.Result will be set
    }

    private static void ProcessHtmlEncoding(ActionExecutingContext context)
    {
        context.ActionArguments.ToList().ForEach(arg => { arg.Value.ParseProperties(); });
    }
}
公共静态类HttpEncode
{
公共静态属性(此对象模型)
{
if(model==null)返回;
if(IsPropertyArrayOrList(model.GetType()))
{
ParsePropertiesFlist(模型);
}
其他的
{
ForEach(t=>EncodeField(t,model));
}
}
私有静态void parsePropertiesForList(对象模型)
{
foreach(IEnumerable模型中的var项)
{
物业(项目);
}
}
私有静态列表GetAllProperties(对象值)=>value?.GetType()?.GetProperties()?.ToList();
私有静态void EncodeField(PropertyInfo p,object arg)
{
尝试
{
if(p.GetIndexParameters().Length!=0 | | p.GetValue(arg)==null)
返回;
if(IsUserDefinedClass(p.PropertyType)和&p.CanWrite)
{
ParseProperties(p.GetValue(arg));
}
else if(IsPropertyArrayOrList(p.PropertyType)和&p.CanWrite)
{
ParseArrayOrListProperty(p,arg);
}
else if(p.PropertyType==typeof(string)&&p.CanWrite)
{
var encodedValue=HtmlEncode(p.GetValue(arg)?.ToString();
SetPropertyValue(p,arg,encodedValue);
}
}
捕获(例外情况除外)
{
//忽略
}
}
私有静态void ParseArrayOrListProperty(PropertyInfo p,object arg)
{
如果(p.GetValue(arg)是字符串[]| | p.GetValue(arg)是列表)
{
StatingrayType的SetPropertyValue(p,arg);
}
其他的
{
parsePropertiesFlist(p.GetValue(arg));
}
}
私有静态void SetPropertyValueOfStaringRayType(PropertyInfo PropertyInfo,对象arg)
{
if(propertyInfo.GetValue(arg)是字符串[]stringValue)
{
var result=新列表();
ForEach(l=>result.Add(HtmlEncode(l));
SetPropertyValue(propertyInfo,arg,result.Any()?result.ToArray():null);
}
else if(propertyInfo.GetValue(arg)是List listValue)
{
var result=新列表();
ForEach(l=>result.Add(HtmlEncode(l));
SetPropertyValue(propertyInfo,arg,result.Any()?结果:null);
}
}
私有静态bool IsUserDefinedClass(类型)=>
type.IsClass&&
!type.FullName.StartsWith(“系统”);
私有静态bool IsPropertyArrayOrList(类型)=>
type.IsArray&&type.GetElementType()==typeof(字符串)||
(type!=typeof(string)和&type.GetInterface(typeof(IEnumerable.FullName)!=null);
私有静态void SetPropertyValue(PropertyInfo PropertyInfo、object allValue、object value)
{
propertyInfo.SetValue(allValue,value);
}
私有静态字符串HtmlEncode(字符串值)=>HttpUtility.HtmlEncode(值);
}
公共类EncodeInputsActionFilter:IAsyncActionFilter
{
公共异步任务OnActionExecutionAsync(
ActionExecutingContext上下文,
ActionExecutionDelegate(下一步)
{
ProcessHtmlEncoding(上下文);
var resultContext=wait next();
//在操作执行后执行操作;resultContext.Result将被设置
}
私有静态void ProcessHtmlEncoding(ActionExecutingContext上下文)
{
context.ActionArguments.ToList().ForEach(arg=>{arg.Value.ParseProperties();});
}
}

。讨论基本上指向感谢你。是的,对于所有视图和操作,我基本上都需要这样做。但是,我目前正在开发的应用程序没有正确设置,我想为所有操作设置一个操作过滤器,并在最顶层捕获注入。否则,我需要对代码进行大量更改。您可以查看并在全局或控制器级别应用它。Hthyes,动作过滤器是最好的方法。我已经创建了自己的逻辑来编码字符串。