如:
当然我们一般都是按照提示来把framework版本设置2.0来解决。为什么可以这么解决了,还有没有其它的解决方法了。
先让我们看看QueryString的源代码吧:
复制代码 代码如下:
public NameValueCollection QueryString
{
get
{
if (this._queryString == null)
{
this._queryString = new HttpValueCollection();
if (this._wr != null)
{
this.FillInQueryStringCollection();
}
this._queryString.MakeReadOnly();
}
if (this._flags[1])
{
this._flags.Clear(1);
this.ValidateNameValueCollection(this._queryString, RequestValidationSource.QueryString);
}
return this._queryString;
}
}
private void FillInQueryStringCollection()
{
byte[] queryStringBytes = this.QueryStringBytes;
if (queryStringBytes != null)
{
if (queryStringBytes.Length != 0)
{
this._queryString.FillFromEncodedBytes(queryStringBytes, this.QueryStringEncoding);
}
}
else if (!string.IsNullOrEmpty(this.QueryStringText))
{
this._queryString.FillFromString(this.QueryStringText, true, this.QueryStringEncoding);
}
}
先让我们插入一点 那就是QueryString默认已经做了url解码。 其中HttpValueCollection的 FillFromEncodedBytes方法如下
复制代码 代码如下:
internal void FillFromEncodedBytes(byte[] bytes, Encoding encoding)
{
int num = (bytes != null) ? bytes.Length : 0;
for (int i = 0; i < num; i++)
{
string str;
string str2;
this.ThrowIfMaxHttpCollectionKeysExceeded();
int offset = i;
int num4 = -1;
while (i < num)
{
byte num5 = bytes[i];
if (num5 == 0x3d)
{
if (num4 < 0)
{
num4 = i;
}
}
else if (num5 == 0x26)
{
break;
}
i++;
}
if (num4 >= 0)
{
str = HttpUtility.UrlDecode(bytes, offset, num4 - offset, encoding);
str2 = HttpUtility.UrlDecode(bytes, num4 + 1, (i - num4) - 1, encoding);
}
else
{
str = null;
str2 = HttpUtility.UrlDecode(bytes, offset, i - offset, encoding);
}
base.Add(str, str2);
if ((i == (num - 1)) && (bytes[i] == 0x26))
{
base.Add(null, string.Empty);
}
}
}
从这里我们可以看到QueryString已经为我们做了解码工作,我们不需要写成 HttpUtility.HtmlDecode(Request.QueryString["xxx"])而是直接写成Request.QueryString["xxx"]就ok了。
现在让我们来看看你QueryString的验证,在代码中有
复制代码 代码如下:
if (this._flags[1])
{
this._flags.Clear(1);
this.ValidateNameValueCollection(this._queryString, RequestValidationSource.QueryString);
}
一看this.ValidateNameValueCollection这个方法名称就知道是干什么的了,验证QueryString数据;那么在什么情况下验证的了?
让我们看看this._flags[1]在什么地方设置的:
复制代码 代码如下:
public void ValidateInput()
{
if (!this._flags[0x8000])
{
this._flags.Set(0x8000);
this._flags.Set(1);
this._flags.Set(2);
this._flags.Set(4);
this._flags.Set(0x40);
this._flags.Set(0x80);
this._flags.Set(0x100);
this._flags.Set(0x200);
this._flags.Set(8);
}
}
而该方法在ValidateInputIfRequiredByConfig中调用,调用代码
复制代码 代码如下:
internal void ValidateInputIfRequiredByConfig()
{
.........
if (httpRuntime.RequestValidationMode >= VersionUtil.Framework40)
{
this.ValidateInput();
}
}
我想现在大家都应该明白为什么错题提示让我们把framework改为2.0了吧。应为在4.0后才验证。这种解决问题的方法是关闭验证,那么我们是否可以改变默认的验证规则了?
让我们看看ValidateNameValueCollection
复制代码 代码如下:
private void ValidateNameValueCollection(NameValueCollection nvc, RequestValidationSource requestCollection)
{
int count = nvc.Count;
for (int i = 0; i < count; i++)
{
string key = nvc.GetKey(i);
if ((key == null) || !key.StartsWith("__", StringComparison.Ordinal))
{
string str2 = nvc.Get(i);
if (!string.IsNullOrEmpty(str2))
{
this.ValidateString(str2, key, requestCollection);
}
}
}
}
private void ValidateString(string value, string collectionKey, RequestValidationSource requestCollection)
{
int num;
value = RemoveNullCharacters(value);
if (!RequestValidator.Current.IsValidRequestString(this.Context, value, requestCollection, collectionKey, out num))
{
string str = collectionKey + "=\"";
int startIndex = num - 10;
if (startIndex <= 0)
{
startIndex = 0;
}
else
{
str = str + "...";
}
int length = num + 20;
if (length >= value.Length)
{
length = value.Length;
str = str + value.Substring(startIndex, length - startIndex) + "\"";
}
else
{
str = str + value.Substring(startIndex, length - startIndex) + "...\"";
}
string requestValidationSourceName = GetRequestValidationSourceName(requestCollection);
throw new HttpRequestValidationException(SR.GetString("Dangerous_input_detected", new object[] { requestValidationSourceName, str }));
}
}
哦?原来一切都明白了,验证是在RequestValidator做的。
复制代码 代码如下:
public class RequestValidator
{
// Fields
private static RequestValidator _customValidator;
private static readonly Lazy<RequestValidator> _customValidatorResolver = new Lazy<RequestValidator>(new Func<RequestValidator>(RequestValidator.GetCustomValidatorFromConfig));
// Methods
private static RequestValidator GetCustomValidatorFromConfig()
{
HttpRuntimeSection httpRuntime = RuntimeConfig.GetAppConfig().HttpRuntime;
Type userBaseType = ConfigUtil.GetType(httpRuntime.RequestValidationType, "requestValidationType", httpRuntime);
ConfigUtil.CheckBaseType(typeof(RequestValidator), userBaseType, "requestValidationType", httpRuntime);
return (RequestValidator) HttpRuntime.CreatePublicInstance(userBaseType);
}
internal static void InitializeOnFirstRequest()
{
RequestValidator local1 = _customValidatorResolver.Value;
}
private static bool IsAtoZ(char c)
{
return (((c >= 'a') && (c <= 'z')) || ((c >= 'A') && (c <= 'Z')));
}
protected internal virtual bool IsValidRequestString(HttpContext context, string value, RequestValidationSource requestValidationSource, string collectionKey, out int validationFailureIndex)
{
if (requestValidationSource == RequestValidationSource.Headers)
{
validationFailureIndex = 0;
return true;
}
return !CrossSiteScriptingValidation.IsDangerousString(value, out validationFailureIndex);
}
// Properties
public static RequestValidator Current
{
get
{
if (_customValidator == null)
{
_customValidator = _customValidatorResolver.Value;
}
return _customValidator;
}
set
{
if (value == null)
{
throw new ArgumentNullException("value");
}
_customValidator = value;
}
}
}
主要的验证方法还是在CrossSiteScriptingValidation.IsDangerousString(value, out validationFailureIndex);而CrossSiteScriptingValidation是一个内部类,无法修改。
让我们看看CrossSiteScriptingValidation类大代码把
复制代码 代码如下:
internal static class CrossSiteScriptingValidation
{
// Fields
private static char[] startingChars = new char[] { '<', '&' };
// Methods
private static bool IsAtoZ(char c)
{
return (((c >= 'a') && (c <= 'z')) || ((c >= 'A') && (c <= 'Z')));
}
internal static bool IsDangerousString(string s, out int matchIndex)
{
matchIndex = 0;
int startIndex = 0;
while (true)
{
int num2 = s.IndexOfAny(startingChars, startIndex);
if (num2 < 0)
{
return false;
}
if (num2 == (s.Length - 1))
{
return false;
}
matchIndex = num2;
char ch = s[num2];
if (ch != '&')
{
if ((ch == '<') && ((IsAtoZ(s[num2 + 1]) || (s[num2 + 1] == '!')) || ((s[num2 + 1] == '/') || (s[num2 + 1] == '?'))))
{
return true;
}
}
else if (s[num2 + 1] == '#')
{
return true;
}
startIndex = num2 + 1;
}
}
internal static bool IsDangerousUrl(string s)
{
if (string.IsNullOrEmpty(s))
{
return false;
}
s = s.Trim();
int length = s.Length;
if (((((length > 4) && ((s[0] == 'h') || (s[0] == 'H'))) && ((s[1] == 't') || (s[1] == 'T'))) && (((s[2] == 't') || (s[2] == 'T')) && ((s[3] == 'p') || (s[3] == 'P')))) && ((s[4] == ':') || (((length > 5) && ((s[4] == 's') || (s[4] == 'S'))) && (s[5] == ':'))))
{
return false;
}
if (s.IndexOf(':') == -1)
{
return false;
}
return true;
}
internal static bool IsValidJavascriptId(string id)
{
if (!string.IsNullOrEmpty(id))
{
return CodeGenerator.IsValidLanguageIndependentIdentifier(id);
}
return true;
}
}
结果我们发现&# <! </ <? <[a-zA-z] 这些情况验证都是通不过的。
所以我们只需要重写RequestValidator就可以了。
例如我们现在需要处理我们现在需要过滤QueryString中k=&...的情况
复制代码 代码如下:
public class CustRequestValidator : RequestValidator
{
protected override bool IsValidRequestString(HttpContext context, string value, RequestValidationSource requestValidationSource, string collectionKey, out int validationFailureIndex)
{
validationFailureIndex = 0;
//我们现在需要过滤QueryString中k=&...的情况
if (requestValidationSource == RequestValidationSource.QueryString&&collectionKey.Equals("k")&& value.StartsWith("&"))
{
return true;
}
return base.IsValidRequestString(context, value, requestValidationSource, collectionKey, out validationFailureIndex);
}
}
<httpRuntime requestValidationType="MvcApp.CustRequestValidator"/>
个人在这里只是提供一个思想,欢迎大家拍砖!
相关推荐:
用AI写文,开启创作新时代
SEO技巧提升网站流量:打造高效网站的关键策略,Ai测脸相
AI网站开发与代码创新:引领未来数字化变革的关键,ai ay规则
SEO获客的秘诀:如何通过搜索引擎优化提升客户获取能力,厦门seo搜索优化排名
seo需要买什么,seo需要考虑什么 ,ai做表头
AI提炼主要内容:如何让信息更精准、高效、易懂,女军人ai
SEO就是:让你的品牌脱颖而出,获得更多曝光与流量,梅岭关键词排名优化
ChatGPT空白对话:释放创意,开启智能对话的新世界,ai重庆南坪
ChatGPT为什么访问不了了?了解背后的原因与解决方法,AI怎么拖入路径
ChatGPT发生故障,背后隐藏着哪些不为人知的原因与挑战?,硬件ai和软件ai
ChatGPT登录界面都不显示了?可能是这些原因导致的!,上海小学ai智能课
ChatGPT昨晚突然不能使用,背后真相令人意想不到!,edga ai
代哥SEO-让您的网站迅速登顶搜索引擎的秘密武器,济南关键词的排名优化
SEO网:让你的数字营销更加精准高效,开启网络引流新时代,丰县互联网网站推广优势
ChatGPT显示无法加载网站是怎么回事?解决方法!,glow将军ai
seo渠道优化是什么,seo渠道推广怎么做 ,ai121333
seo重点是什么,seo最重要的指标 ,ai网格怎么用
SEO站群:打造强大网络营销引擎,助力企业快速提升排名与流量,seo网站排名案例
SEO优化排名:让您的网站在搜索引擎中脱颖而出,我ai 达瓦仓决
ChatGPT内部HTTP接口文档-为开发者提供高效便捷的AI服务接入方式,安屿ai
OpenAI账号申诉怎么办?全方位解析解决方案,ai写作免费公众号下载
SEO优化中怎么找关键词:全面解析与实战技巧,ai2002.4.8
揭开“好的AI软件”背后的秘密:让生活和工作更智能的利器
seo软文用什么论坛,seo软文是什么意思 ,爱字幕的AI变脸不见了
seo跟sem是什么,seo和sem的概念 ,惠威的ai功能
SEO教育:搜索引擎优化,开启成功职业之路,搜狗SEO排名接单
智能AI生成文章释放创作新可能
什么是seo方法,何为seo ,ai写作神器源码是什么
SEO在线服务-让您的网站快速跃升至搜索引擎前列,江西小红书营销推广案例
ChatGPT-深度学习与自然语言处理的革命性突破,金华ai视觉锁螺丝机
SEO公司核心业务是什么?揭秘提升网站排名的奥秘,写作助手ai一键生成作文在线
SEO笔记:如何打造高效的SEO策略提升网站排名,网站优化优质服务方案
为什么要seo 运营,为什么需要seo ,ai人物头盔
SEO优化关键技巧:提升网站排名的实战攻略,科大讯飞ai论文写作软件
seo要学会什么,seo要学多长时间 ,NTU AI 录取
ChatGPT的超链接点不开?解决方法一网打尽!,情感ai写作指令是什么
seo网页优化什么意思,seo网站优化必知的10个问答,问吧,【解决】百度不知道 ,ai识别点读机
SEO自行:提升网站流量的秘密武器,邹平县个人网站建设建议
ChatGPT故障你从未听过的真相,究竟是什么让它偶尔“失灵”?,ai 图片 矢量
seo需要什么人员,seo需要什么技能 ,画大学ai
AI免费生成:开启智能创作新纪元,助力你的创意无限可能
什么是seo如何进行seo,何谓seo ,红米的AI摄影什么意思
怎么用AI写出高质量科普文章?揭秘新时代创作利器!
seo配置是什么,seo设置是什么 ,ai图标制作教程
AI一键生成原创文章,让创作更高效更轻松!
seo项目是什么,seo是啥 ,ai ued
SEO模块:提升网站排名,驾驭数字营销未来,营口网站建设制作平台
《收录情况:数字时代的网络信息检索与价值体现》,山东全域营销推广软件客服电话
ChatGPT为什么打不开了?揭秘背后的原因与解决办法,ai业务后端
企业关键字-助力企业成功的隐形动力,闽侯县企业网站建设