本文轉載自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());
}