Danes zjutraj mi je kolega zastavil vprašanje: rekel sem, da so prejeti parametri popačeni, dovolite, da pomagam rešiti težavo.
Platforma, za katero je odgovoren moj kolega, je zgrajena Ext.js ogrodju, konfiguracijska datoteka web.config pa je konfigurirana z globalnim kodiranjem "GB2312":
<globalization requestEncoding="gb2312" responseEncoding="gb2312" fileEncoding="gb2312" culture="zh-CN"/>
Ko frontend pošlje "kitajsko besedilo", backend prejme popačene znake z Request.QueryString["xxx"].
Ne glede na to, kako dekodiraš s System.Web.HttpUtility.UrlDecode("xxx", "encoding type"), ne deluje.
Opis načela: 1: Prva stvar, ki jo je treba ugotoviti, je, da Ext.js ob oddaji URL parametrov odjemalca kodirala pred oddajo, pri čemer je kodiranje odjemalca privzeto UTF-8 kodiranje
2: Zakaj je potem popačen, ko prejemam parametre s Request.QueryString["xxx"]?
Prevajanje obrnemo korak za korakom, 2.1: Oglejte si kodo lastnosti QueryString:
- 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;
- }
- }
Kopiraj kodo
2.2: Vključite metodo FillInQueryStringCollection()
- 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);
-
- }
- }
Kopiraj kodo
2.3: Rez: 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);
- }
- }
Kopiraj kodoIz kode QueryStringEncoding sistem privzeto uporablja metodo kodiranja globalizacijskega konfiguracijskega vozlišča, če pa ne, je privzeto kodiranje UTF-8 2.4: Izrezovanje v FillFromString (string s, bool urlenkodiran, kodiranje kodiranja)
- 代码有点长,就折叠起来了
- 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);
- }
- }
- }
Kopiraj kodoOd tu naprej ugotovimo, da se vsi vhodi parametrov kličejo enkrat: HttpUtility.UrlDecode(str2, kodiranje);
Ko odjemalec js pošlje kitajščino strežniku v utf-8 kodiranju, ga ob prejemu z Request.QueryString najprej enkrat dekodira z gb2312, konfiguriranim z globalizacijo, kar povzroči popačene znake.
1: Metoda kodiranja JS je URT-8
2: Strežniška stran je privzeto nastavila na GB2312
3: Request.QueryString bo privzeto klical HttpUtility.UrlDecode za dekodiranje prejetih parametrov s sistemskim konfiguracijskim kodiranjem.
1: Sistem izbere privzeto kodiranje v naslednjem vrstnem redu: HTTP header request - >globalization configuration node - default UTF-8
2: Ko URL vnesete neposredno v kitajščino, ga lahko različni brskalniki obravnavajo različno, na primer: IE ne kodira in pošilja neposredno, Firefox pa pošlje URL po kodiranju GB2312.
3: Za nekodirane "kitajske znake", po uporabi Request.QueryString interni klic HttpUtility.UrlDecode, avtor gb2312->utf-8,
Če kitajski znak ni najden, se privzeto pretvori v "%ufffd", kar povzroči nepovratne popačene znake.
4: Pot do rešitve Če poznamo načelo, obstaja veliko načinov, kako ga rešiti: 1: Globalna enotnost je kodiranje UTF-8, kar prihrani težave in skrbi.
2: Ko je GB2312 globalno določen, je URL kitajski, js pa mora biti kodiran, na primer ext.js framework.
Na ta način ga lahko upravljate le posebej, pri čemer določite kodiranje in dekodiranje na strežniški strani. Ker privzeti sistem enkrat pokliče HttpUtility.UrlDecode ("xxx", kodiranje sistemske konfiguracije), Torej ponovno pokličete HttpUtility.UrlEncode ("xxx", kodiranje, ki ga konfigurira sistem), da se vrnete na prvotni urt-8 parameter kodiranja
Nato uporabite HttpUtility.UrlDecode("xxx", utf-8) za dekodiranje. niz aaa = zahteva. Request.QueryString["admin"]; Lastnik doma string a1 = HttpUtility.UrlEncode(aaa, System.Text.Encoding.GetEncoding("GB2312")); string a2 = HttpUtility.UrlDecode(a1,System.Text.Encoding.UTF8);
|