深度解析Asp.net中的验证和Mvc对它的继承

1.HttpRequest.ValidateInput() 只是设置一个标志,这个标志就是_flags[0x8000],是启用验证开关标志(另外还启用了其他一些标志),

  HttpRequest.ValidateInputWasCalled就是根绝这个启用验证开关标志来判断的这个标志很重要,见后面说明。

2.ValidationUtility.EnableDynamicValidation是调用DynamicValidationShimReflectionUtil(反射垫片),

  DynamicValidationShimReflectionUtil(反射垫片)以反射方式调用DynamicValidationShimDynamicValidationShim调用HttpRequest

  的EnableGranularRequestValidation来设置_enableGranularValidation为true, 表示需要细粒度的验证

 

  这个细粒度的验证的意思:其中,HttpRequest在Form,QueryString,Heads,Cookie,Files的get读取器访问时会调用到以下三个方法:

  HttpRequest的ValidateHttpValueCollection()、ValidateCookieCollection()、ValidatePostedFileCollection()。在调用它们时会判断

  _enableGranularValidation是否为true,

  如果是true则表示启用颗粒级的验证,会等到调用Form,QueryString,File的 Get/this[""](this索引器其实调用的也是Get方法)方法时才会去调用验证函数来验证值,

  如果是false,则一访问Form或QuetyString,Header属性时则就马上调用验证函数

 

3.而上面说的验证函数实际上就是HttpRequest的ValidateString函数,这个函数主要是调用RequestValidatorIsValidRequestString

   IsValidRequestString是用来验证危险字符的,不过它不会去验证HttpHead,也就是说HttpHeaderCollection的串不论传的是什么格式始终是有效的不会被服务端验证的,

  原因尚待研究。详情见RequestValidatorIsValidRequestString方法。

 

4.调用到EnableGranularRequestValidation的方法:在ValidationUtility.EnableDynamicValidation() 和

   HttpRequest.ValidateInputIfRequiredByConfig()【.NET4.5有调用到】【.net4.5默认启用细粒度的验证

 

  ValidationUtility.EnableDynamicValidation调用它的几个地方有:

  1、MvcHandler的ProcessRequestInit方法:这个方法会判断HttpRequest的_flags是否设置了已启用验证的位(HttpRequest.RequestValidationCalled),如果已启用,则启用颗粒验证

  2、ControllerActionInvoker的ValidateRequest方法:这个方法总是会被调用, 因为它时根据controllerBase中的ValidateRequest属性是否为true来调用,

     而ValidateRequest总是默认为true,除非使用ValidateInputAttribute来修改这个属性

  3、ValidationUtility的GetUnvalidatedCollections

  4、WebPageHttpHandler的ProcessRequestInternal

 

  而调用HttpRequest.ValidateInputIfRequiredByConfig()调用它的几个地方有

  1、ValidateRequestExecutionStep。

  2、PipelineStepManager

  如果是ValidateInputIfRequiredByConfig总是会去设置

 

  所以是大于.net4.0,总会调用HttpRequest.ValidateInput,这样总是会启用验证(RequestValidationCalled总是为true),而什么时候开始验证,则是判断_enableGranularValidation是否为true

  在MVC3中,因为调用了MvcHandler的ProcessRequestInit方法,ProcessRequestInit又调用EnableDynamicValidation(前提是RequestValidationCalled为true),所以_enableGranularValidation总为true,

  而在webform4.0里,因为没有地方调用EnableDynamicValidation或ValidateInputIfRequiredByConfig,_enableGranularValidation总为false,在webform中如果有非法字符,

  一旦访问Form,Headers或QueryString就会报错

 

  所以ValidateInput的作用貌似是这样,先将HttpRuntime节点的RequestValidationMode设置为2.0,这样RequestValidationCalled的开关被关掉了,

  Mvc执行Action之后,没有地方去调用ValidationUtility.EnableDynamicValidationle了,然后再开启ValidateInputAttribute(true),这样就可以自由控制了

 

RequestValidationMode:

2.0 仅对网页启用请求验证。是启用还是关闭取决于页面的 validateRequest。

4.0 默认值。任何 HTTP 请求都会

 

HttpRuntimeSection s = ConfigurationManager.GetSection("system.web/httpRuntime") as HttpRuntimeSection;

var bi = s.RequestValidationMode;

FieldInfo fi = typeof(HttpRequest).GetField("_enableGranularValidation", System.Reflection.BindingFlags.NonPublic | System.Reflection.BindingFlags.Instance);

var b = fi.GetValue(System.Web.HttpContext.Current.Request;

 

原文地址:https://www.cnblogs.com/yuuki/p/3307516.html