Bu sabah bir meslektaşım bana bir soru sordu: Alınan parametrelerin karıştığını söyledim, sorunu çözmeme yardım edeyim.
Meslektaşımın sorumlu olduğu platform Ext.js çerçeve oluşturulmuş ve web.config yapılandırma dosyası küresel "GB2312" kodlamasıyla yapılandırılmıştır:
<küreselleşme istekliKodlama="gb2312" yanıtıKodlama="gb2312" dosyaKodlama="gb2312" kültür="zh-CN"/>
Ön uç "Çince metni"ni gönderdiğinde, arka uç Request.QueryString["xxx"] ile bozulmuş karakterler alır.
System.Web.HttpUtility.UrlDecode("xxx", "encoding type") ile nasıl çözerseniz alın, bu yöntem işe yaramıyor.
İlke açıklaması: 1: İlk belirlenmesi gereken şey, istemcinin URL parametreleri gönderildiğinde, Ext.js bunları göndermeden önce kodlayacak ve istemcinin kodlaması varsayılan olarak UTF-8 kodlamasıdır
2: O zaman Request.QueryString["xxx"] ile parametreler alındığında neden bozuluyor?
Derlemeyi adım adım geri çeviriyoruz, 2.1: QueryString özelliğinin koduna bakın:
- Code highlighting produced by Actipro CodeHighlighter (freeware)http://www.CodeHighlighter.com/-->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);
- ValidateNameValueCollection(this._queryString, "Request.QueryString");
- }
- return this._queryString;
- }
- }
Kopya kodu
2.2: FillInQueryStringCollection() yöntemine kesin
- Code highlighting produced by Actipro CodeHighlighter (freeware)http://www.CodeHighlighter.com/-->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))
- {
- //下面这句是对普通文件提交的处理:FillFromString是个切入点,编码切入点是:this.QueryStringEncoding
- this._queryString.FillFromString(this.QueryStringText, true, this.QueryStringEncoding);
-
- }
- }
Kopya kodu
2.3: Kesme: QueryStringEncoding
- Code highlighting produced by Actipro CodeHighlighter (freeware)http://www.CodeHighlighter.com/-->internal Encoding QueryStringEncoding
- {
- get
- {
- Encoding contentEncoding = this.ContentEncoding;
- if (!contentEncoding.Equals(Encoding.Unicode))
- {
- return contentEncoding;
- }
- return Encoding.UTF8;
- }
- }
- //点击进入this.ContentEncoding则为:
- public Encoding ContentEncoding
- {
- get
- {
- if (!this._flags[0x20] || (this._encoding == null))
- {
- this._encoding = this.GetEncodingFromHeaders();
- if (this._encoding == null)
- {
- GlobalizationSection globalization = RuntimeConfig.GetLKGConfig(this._context).Globalization;
- this._encoding = globalization.RequestEncoding;
- }
- this._flags.Set(0x20);
- }
- return this._encoding;
- }
- set
- {
- this._encoding = value;
- this._flags.Set(0x20);
- }
- }
Kopya koduQueryStringEncoding kodundan sistem, küreselleştirme yapılandırma düğümünün kodlama yöntemine varsayılan olarak geçer ve değilse, varsayılan UTF-8 kodlamasıdır 2.4: FillFromString'e Cut (string s, bool urlencoded, Kodlama kodlama)
- 代码有点长,就折叠起来了
- Code highlighting produced by Actipro CodeHighlighter (freeware)http://www.CodeHighlighter.com/-->internal void FillFromString(string s, bool urlencoded, Encoding encoding)
- {
- int num = (s != null) ? s.Length : 0;
- for (int i = 0; i < num; i++)
- {
- int startIndex = i;
- int num4 = -1;
- while (i < num)
- {
- char ch = s[i];
- if (ch == '=')
- {
- if (num4 < 0)
- {
- num4 = i;
- }
- }
- else if (ch == '&')
- {
- break;
- }
- i++;
- }
- string str = null;
- string str2 = null;
- if (num4 >= 0)
- {
- str = s.Substring(startIndex, num4 - startIndex);
- str2 = s.Substring(num4 + 1, (i - num4) - 1);
- }
- else
- {
- str2 = s.Substring(startIndex, i - startIndex);
- }
- if (urlencoded)//外面的传值默认是true,所以会执行以下语句
- {
- base.Add(HttpUtility.UrlDecode(str, encoding), HttpUtility.UrlDecode(str2, encoding));
- }
- else
- {
- base.Add(str, str2);
- }
- if ((i == (num - 1)) && (s[i] == '&'))
- {
- base.Add(null, string.Empty);
- }
- }
- }
Kopya koduBu noktadan itibaren tüm parametre girdilerinin bir kez çağrıldığını görüyoruz: HttpUtility.UrlDecode(str2, kodlama);
İstemci js, Çince'yi utf-8 kodlamasında sunucuya gönderdiğinde, Request.QueryString ile aldığında, önce gb2312 ile küreselleştirme ile bir kez kod çözer ve bu da karakterlerin karışıklığına yol açar.
1: JS kodlama yöntemi URT-8'dir
2: Sunucu tarafı varsayılan GB2312 olarak yapılandırıldı
3: Request.QueryString, alınan parametreleri sistem yapılandırma kodlamasıyla çözmek için varsayılan olarak HttpUtility.UrlDecode'u çağırır.
1: Sistem varsayılan kodlamayı şu sırayla seçer: http istek başlığı - >küreselleştirme yapılandırma düğümü - varsayılan UTF-8
2: URL doğrudan Çince'ye girildiğinde, farklı tarayıcılar farklı şekilde işleyebilir, örneğin: IE kodlamaz ve doğrudan gönderir, Firefox GB2312 kodlamasından sonra URL'yi gönderir.
3: Kodlanmamış "Çince karakterler" için, Request.QueryString dahili çağrısı HttpUtility.UrlDecode kullanıldıktan sonra, gb2312->utf-8 tarafından,
Çince karakter bulunmazsa, varsayılan olarak "%ufffd"ye dönüştürülür ve geri döndürülemez bozuk karakterler oluşur.
4: Çözüme giden yol İlkesi bildiğimde, çözmenin birçok yolu vardır: 1: Küresel birleştirme UTF-8 kodlamasıdır, bu da sorun ve endişeyi azaltır.
2: GB2312 küresel olarak tanımlandığında, URL Çincedir ve js kodlanmalıdır, örneğin ext.js çerçeve gibi.
Bu şekilde, sunucu tarafında kodlama ve çözme sistemini belirleyerek özel olarak yönetebilirsiniz. Varsayılan sistem HttpUtility.UrlDecode("xxx", sistem yapılandırmasının kodlaması) bir kez çağırdığı için, Bu yüzden HttpUtility.UrlEncode("xxx", sistem tarafından yapılandırılan kodlama) tekrar çağırarak orijinal urt-8 kodlama parametresine geri dönersiniz
Sonra HttpUtility.UrlDecode("xxx", utf-8) kullanarak kod çözebilirsiniz. Dizi aaa = istek. Request.QueryString["admin"]; Ev Sahibi string a1 = HttpUtility.UrlEncode(aaa, System.Text.Encoding.GetEncoding("GB2312")); dizi a2 = HttpUtility.UrlDecode(a1,System.Text.Encoding.UTF8);
|