本文转载自https://www.cnblogs.com/ruanyifeng/p/4739807.html。对第二种过滤方法的代码进行了一些修改和注释,记录一下免得以后忘了。已经测试过,应该可以直接复制到项目中直接使用了。
通过了解Web Api的pipeline机制(管道机制),发现可以在两个地方进行参数的过滤
重写DelegatingHandler的SendAsync方法进行过滤
public class AntiXssHttpMessageHandler : DelegatingHandler
{
protected override System.Threading.Tasks.Task<HttpResponseMessage> SendAsync(HttpRequestMessage Request, System.Threading.CancellationToken cancellationToken)
{
foreach (var key in Request.RequestUri.ParseQueryString().AllKeys)
{
var value = Sanitizer.GetSafeHtmlFragment(Request.RequestUri.ParseQueryString()[key]);
if (value != Request.RequestUri.ParseQueryString()[key])
{
throw new Exception();
}
}
return base.SendAsync(Request, cancellationToken);
}
}
public static class WebApiConfig
{
public static void Register(HttpConfiguration config)
{
config.Routes.MapHttpRoute(
name: "DefaultApi",
routeTemplate: "api/{controller}/{id}",
defaults: new { id = RouteParameter.Optional }
);
config.EnableSystemDiagnosticsTracing();
config.MessageHandlers.Add(new AntiXssHttpMessageHandler());
}
}
重写ApiControllerActionInvoker的InvokeActionAsync方法
public class XssActionInvoker : ApiControllerActionInvoker
{
public override Task<HttpResponseMessage> InvokeActionAsync(HttpActionContext actionContext, CancellationToken cancellationToken)
{
//请求头参数处理---未实现
Dictionary<string, object> changeDictionary = new Dictionary<string, object>();
//上下文参数处理
foreach (var para in actionContext.ActionArguments)
{
var paraType = para.Value.GetType();
//string类型参数,一般为uri上的参数
if (paraType == typeof(string))
{
var value = para.Value.ToString();
if (!string.IsNullOrWhiteSpace(value))
{
value = Sanitizer.GetSafeHtmlFragment(value);//移除有危险的html标签 比如<script>
//value = System.Web.HttpUtility.HtmlEncode(value);//将html标签进行编码
changeDictionary.Add(para.Key, value);
}
}
else if (paraType.IsClass)
{
var properties = paraType.GetProperties();
bool flag = false;
foreach (var e in properties)
{
if (e.PropertyType == typeof(string))
{
var value = e.GetValue(para.Value) as string;
if (!string.IsNullOrWhiteSpace(value))
{
value = Sanitizer.GetSafeHtmlFragment(value);
e.SetValue(para.Value, value);
flag = true;
}
}
}
if (flag)
{
changeDictionary.Add(para.Key, para.Value);
}
}
}
foreach (var para in changeDictionary)
{
actionContext.ActionArguments[para.Key] = para.Value;
}
return base.InvokeActionAsync(actionContext, cancellationToken);
}
}
protected void Application_Start()
{
GlobalConfiguration.Configuration.Services.Replace(typeof(IHttpActionInvoker), new XssActionInvoker());
}