Täna hommikul küsis kolleeg minult küsimuse: ütlesin, et saadud parameetrid olid segased, las ma aitan selle lahendada.
Platvorm, mille eest mu kolleeg vastutab, on ehitatud Ext.js raamistik ning web.config konfiguratsioonifail on konfigureeritud globaalse "GB2312" kodeeringuga:
<globalization requestEncoding="gb2312" responseEncoding="gb2312" fileEncoding="gb2312" culture="zh-CN"/>
Kui esiosa esitab "hiina teksti", saab taustsüsteem segased märgid Request.QueryString["xxx"].
Ükskõik kuidas sa dekodeerid System.Web.HttpUtility.UrlDecode("xxx", "kodeerimistüüp"), see ei tööta.
Põhimõtte kirjeldus: 1: Esimene asi, mida määrata, on see, et kui kliendi URL-i parameetrid esitatakse, kodeerib Ext.js need enne esitamist ning kliendi kodeeringuks on vaikimisi UTF-8 kodeerimine
2: Miks siis on see segane, kui saab parameetreid Request.QueryString["xxx"]?
Pöörame kompilatsiooni samm-sammult ümber, 2.1: Vaata QueryStringi omaduse koodi:
- 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;
- }
- }
Kopeeri kood
2.2: Lõika FillInQueryStringCollection() meetodi sisse
- 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);
-
- }
- }
Kopeeri kood
2.3: Lõikamine: 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);
- }
- }
Kopeeri koodQueryStringEncoding koodist lähtudes valib süsteem vaikimisi globaliseerimise konfiguratsioonisõlme kodeerimismeetodi, ja kui mitte, siis vaikimisi on UTF-8 kodeerimine 2.4: Lõika FillFromStringi (string s, bool urlencoded, kodeerimine)
- 代码有点长,就折叠起来了
- 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);
- }
- }
- }
Kopeeri koodSellest punktist leiame, et kõik parameetrisisendid kutsutakse ühe korra: HttpUtility.UrlDecode(str2, kodeerimine);
Kui klient js esitab serverile hiina keele utf-8 kodeeringus, siis Request.QueryStringiga saades dekodeeritakse see esmalt gb2312-ga, mis on globaliseerimise poolt seadistatud, põhjustades segased märgid.
1: JS kodeerimismeetod on URT-8
2: Serveri pool on vaikimisi seadistanud GB2312-ks
3: Request.QueryString kutsub vaikimisi HttpUtility.UrlDecode, et dekodeerida vastuvõetud parameetreid süsteemikonfiguratsiooniga.
1: Süsteem valib vaikimisi kodeeringu järgmises järjekorras: http päringu päis - >globaliseerimise konfiguratsioonisõlm - vaikimisi UTF-8
2: Kui URL sisestatakse otse hiina keelde, võivad erinevad brauserid seda erinevalt käsitleda, näiteks: IE ei kodeeri ja esitab otse, Firefox esitab URL-i pärast GB2312 kodeerimist.
3: Kodeerimata "hiina märkide" puhul, pärast Request.QueryStringi sisemise kutse HttpUtility.UrlDecode kasutamist, autorilt gb2312->utf-8,
Kui hiina märki ei leita, teisendatakse see vaikimisi "%ufffd"-ks, mille tulemusena on pöördumatud segased märgid.
4: Tee lahenduseni Põhimõtet teades on palju võimalusi selle lahendamiseks: 1: Globaalne ühtlustamine on UTF-8 kodeerimine, mis säästab probleeme ja muret.
2: Kui GB2312 on globaalselt määratletud, on URL hiina keeles ja js tuleb kodeerida, näiteks ext.js raamistik.
Nii saad seda teha ainult spetsiaalselt, määrates kodeerimise ja dekodeerimise serveri poolel. Kuna vaikimisi süsteem kutsub HttpUtility.UrlDecode'i ("xxx", süsteemi konfiguratsiooni kodeerimine) korra, Seega kutsud uuesti HttpUtility.UrlEncode'i ("xxx", süsteemi poolt seadistatud kodeeringu), et naasta algse urt-8 kodeerimisparameetri juurde
Seejärel kasuta HttpUtility.UrlDecode("xxx", utf-8) selle dekodeerimiseks. string aaa = taotlus. Request.QueryString["admin"]; Koduomanik string a1 = HttpUtility.UrlEncode(aaa, System.Text.Encoding.GetEncoding("GB2312")); string a2 = HttpUtility.UrlDecode(a1,System.Text.Encoding.UTF8);
|