如何集中防止.net core mvc应用程序的脚本注入
how to prevent script injections centrally for .net core mvc application
我只需要一些关于实现逻辑以集中检查是否没有脚本添加到输入的意见。
我打算使用 antiXSS (Sanitizer.GetSafeHtmlFragment("value")) 并检查输出是否为空,这意味着它可能包含脚本并处理错误。
我可以想出一个逻辑来通过模型属性并检查值,如果有任何可疑的东西就会抛出错误。
我想知道是否有更好的方法一次性处理所有输入字段的这种注入,而不是为每个字段添加验证。
假设我有这样的模型:
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(); });
}
}
我只需要一些关于实现逻辑以集中检查是否没有脚本添加到输入的意见。
我打算使用 antiXSS (Sanitizer.GetSafeHtmlFragment("value")) 并检查输出是否为空,这意味着它可能包含脚本并处理错误。 我可以想出一个逻辑来通过模型属性并检查值,如果有任何可疑的东西就会抛出错误。
我想知道是否有更好的方法一次性处理所有输入字段的这种注入,而不是为每个字段添加验证。
假设我有这样的模型:
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(); });
}
}