用于json POST的ASP.Net RequestValidation以匹配Form RequestValidation

时间:2017-06-05 18:19:46

标签: c# asp.net json request-validation

我希望能够以与表单验证(“application / x-www-form-urlencoded”)一致的方式对内容类型“application / json”执行RequestValidation。

我已阅读https://msdn.microsoft.com/en-us/library/system.web.util.requestvalidator(v=vs.110).aspx,但它没有太多帮助。

我正在尝试实现自定义请求验证程序来替换默认的System.Web.Util.RequestValidator。

我也看了https://msdn.microsoft.com/en-us/library/system.web.util.requestvalidator(v=vs.110).aspx

如果我无法一致地验证输入,我可能会删除将json发送到控制器并通过表单强制所有内容的能力 - 这并不理想,因为我想要一些接受json的方法。

我已经对输出进行了编码(如果可能的话),但我仍然需要通过验证输入来进行深度防御,并且理想情况下需要对表格和json进行一致。

不幸的是,许多关于此问题的MSDN文档已经过时了,现在已经无关紧要了。

我正在使用.net 4.6.1作为参考。

以这种方式尝试验证请求是否明智?

1 个答案:

答案 0 :(得分:0)

最后,我实现了一个自定义的ModelBinder ...这是阅读此https://weblogs.asp.net/imranbaloch/security-issue-in-asp-net-mvc3-jsonvalueproviderfactory和此https://gist.github.com/jamescrowley/b8c0c006e7b00e28cbbf

的组合

它修改了请求的来源(RequestValidationSource.Form),使其看起来像一个表单,因此可以在同一个管道中进行验证。

public class JsonValidatingModelBinder : DefaultModelBinder
{
    public override object BindModel(ControllerContext controllerContext, ModelBindingContext bindingContext)
    {
        var result = base.BindModel(controllerContext, bindingContext);
        if (!IsJsonRequest(controllerContext))
        {
            return result;
        }
        if (!bindingContext.ModelMetadata.RequestValidationEnabled)
        {
            return result;
        }
        if (result != null)
        {
            EnsureRequestFieldIsValid(controllerContext, result);
        }
        return result;
    }

    static void EnsureRequestFieldIsValid(ControllerContext controllerContext, object result)
    {
        int index;
        // abusing RequestValidationSource enum
        if (!RequestValidator.Current.InvokeIsValidRequestString(
            controllerContext.HttpContext.ApplicationInstance.Context,
            result.ToString(), RequestValidationSource.Form, null, out index))
        {
            throw new HttpRequestValidationException(
                "A potentially dangerous value was detected from the client ");
        }
    }

    static bool IsJsonRequest(ControllerContext controllerContext)
    {
        return controllerContext.HttpContext.Request.ContentType.StartsWith("application/json", StringComparison.OrdinalIgnoreCase);
    }

并在Global.asax中......

    protected void Application_Start()
    {
        System.Web.Mvc.ModelBinders.Binders.DefaultBinder = new JsonValidatingModelBinder();

    }