Web Api全局预防Xss攻击

本文转载自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());
}
        
posted @ 2019-07-25 23:23  傅小灰  阅读(1421)  评论(0编辑  收藏  举报