HttpRequest 의 Query String 속성 에 대한 인식

10644 단어 HttpRequestQueryString
예 를 들 어물론 우 리 는 제시 에 따라 framework 버 전 을 2.0 으로 설정 하여 해결 합 니 다.왜 이렇게 해결 할 수 있 습 니까?아직 다른 해결 방법 이 있 습 니까?먼저 Query String 의 소스 코드 를 보 여 주세요.
 
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);
}
}
먼저 조금 만 삽입 하 겠 습 니 다.그것 은 Query String 이 기본적으로 url 디 코딩 을 했 습 니 다.그 중에서 HttpValue Collection 의 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]라 고 쓰 면 된다.이제 Query String 의 검증 을 살 펴 보 겠 습 니 다.코드 에
 
if (this._flags[1])
{
this._flags.Clear(1);
this.ValidateNameValueCollection(this._queryString, RequestValidationSource.QueryString);
}
this.Validate NameValue Collection 이라는 방법 이름 을 보면 무엇 을 하 는 지 알 수 있 습 니 다.Query String 데 이 터 를 검증 합 니 다.그럼 어떤 상황 에서 검 증 됐 나 요?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);
}
}
이 방법 은 Validate InputIfRequired ByConfig 에서 호출 되 었 습 니 다.코드
 
internal void ValidateInputIfRequiredByConfig()
{
.........
if (httpRuntime.RequestValidationMode >= VersionUtil.Framework40)
{
this.ValidateInput();
}
}
를 호출 하 는 이 유 를 알 아야 한다 고 생각 합 니 다.4.0 이후 에 야 검증 해 야 한다.이런 문 제 를 해결 하 는 방법 은 검증 을 닫 는 것 입 니 다.그러면 우 리 는 기본 적 인 검증 규칙 을 바 꿀 수 있 습 니까?Validate NameValue Collection
 
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;
}
}
} 
주요 검증 방법 은 역시 CrossSiteScripting Validation.IsDangerousString(value,out validationFailureIndex)이다.한편,CrossSiteScripting Validation 은 내부 클래스 로 수정 할 수 없습니다.CrossSiteScripting Validation 류 의 큰 코드 를 보 여 주세요.
 
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 만 다시 쓰 면 돼.예 를 들 어 우 리 는 지금 우리 가 Query String 에서 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"/>
을 처리 해 야 합 니 다.개인 은 여기 서 하나의 사상 만 제공 할 뿐 입 니 다.벽돌 을 찍 는 것 을 환영 합 니 다!

좋은 웹페이지 즐겨찾기