1.HttpRequest.ValidateInput() 只是设置一个标志,这个标志就是_flags[0x8000],是启用验证开关标志(另外还启用了其他一些标志),
HttpRequest.ValidateInputWasCalled就是根绝这个启用验证开关标志来判断的,这个标志很重要,见后面说明。
2.ValidationUtility.EnableDynamicValidation是调用DynamicValidationShimReflectionUtil(反射垫片),
DynamicValidationShimReflectionUtil(反射垫片)以反射方式调用DynamicValidationShim,DynamicValidationShim调用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函数,这个函数主要是调用RequestValidator的IsValidRequestString,
IsValidRequestString是用来验证危险字符的,不过它不会去验证HttpHead,也就是说HttpHeaderCollection的串不论传的是什么格式始终是有效的不会被服务端验证的,
原因尚待研究。详情见RequestValidator的IsValidRequestString方法。
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;