Tänä aamuna kollega esitti minulta kysymyksen: sanoin, että saadut parametrit olivat sekaisin, autan ratkaisemaan sen.
Alusta, josta kollegani vastaa, on rakennettu Ext.js kehykseen, ja web.config-konfiguraatiotiedosto on konfiguroitu globaalilla "GB2312"-koodauksella:
<globalization requestEncoding="gb2312" responseEncoding="gb2312" fileEncoding="gb2312" culture="zh-CN"/>
Kun frontend lähettää "kiinalaisen tekstin", taustajärjestelmä saa sekaisin olevia merkkejä Request.QueryString["xxx"].
Riippumatta siitä, miten dekoodaat System.Web.HttpUtility.UrlDecode("xxx", "encoding type"), se ei toimi.
Periaatteen kuvaus: 1: Ensimmäinen asia, joka tulee todeta, on, että kun asiakkaan URL-parametrit toimitetaan, Ext.js koodaa ne ennen lähettämistä, ja asiakkaan koodaus on oletuksena UTF-8-koodaus
2: Miksi se sitten on sekaisin, kun vastaanotetaan parametreja Request.QueryString["xxx"]?
Käännämme käännöksen askel askeleelta, 2.1: Katso QueryString-ominaisuuden koodia:
- 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;
- }
- }
Kopioi koodi
2.2: Leikkaa FillInQueryStringCollection()-metodiin
- 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);
-
- }
- }
Kopioi koodi
2.3: Leikkaus: 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);
- }
- }
Kopioi koodiQueryStringEncoding-koodista järjestelmä käyttää oletuksena globalisaatiokonfiguraatiosolmun koodausmenetelmää, ja jos ei, oletus on UTF-8-koodaus 2.4: Leikkaa FillFromStringiin (string s, bool urlencoded, koodauskoodaus)
- 代码有点长,就折叠起来了
- 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);
- }
- }
- }
Kopioi koodiTästä eteenpäin kaikki parametrisyötteet kutsutaan kerran: HttpUtility.UrlDecode(str2, encoding);
Kun asiakas js lähettää kiinaa palvelimelle utf-8-koodauksessa, vastaanottaessaan sen Request.QueryStringillä, se purkaa sen ensin kerran gb2312:lla, joka on globalisaation määrittämä, mikä johtaa sekavoihin merkkeihin.
1: JS-koodausmenetelmä on URT-8
2: Palvelinpuoli on konfiguroinut oletusasetukseksi GB2312
3: Request.QueryString kutsuu oletuksena HttpUtility.UrlDecodea purkaakseen vastaanotetut parametrit järjestelmäkonfiguraatiokoodauksella.
1: Järjestelmä valitsee oletuskoodauksen seuraavassa järjestyksessä: http-pyyntöotsikko - >globalisaatiokonfiguraatiosolmu - oletus UTF-8
2: Kun URL syötetään suoraan kiinaksi, eri selaimet voivat käsitellä sitä eri tavoin, esimerkiksi: IE ei koodaa ja lähettää suoraan, Firefox lähettää URL-osoitteen GB2312-koodauksen jälkeen.
3: Koodaamattomille "kiinalaisille merkeille", käyttäen Request.QueryStringin sisäistä kutsua HttpUtility.UrlDecode, tekijänä gb2312->utf-8,
Jos kiinalaista merkkiä ei löydy, se muunnetaan oletuksena muotoon "%ufffd", mikä johtaa peruuttamattomiin sekavoihin merkkeihin.
4: Ratkaisun tie Kun tuntee periaatteen, on monia tapoja ratkaista se: 1: Globaali yhtenäisyys on UTF-8-koodaus, mikä säästää vaivaa ja huolta.
2: Kun GB2312 määritellään globaalisti, url on kiinaksi, ja js täytyy koodata, kuten ext.js framework.
Näin voit hoitaa sen vain erityisesti, määrittäen koodauksen ja purkamisen palvelinpuolella. Koska oletusjärjestelmä kutsuu HttpUtility.UrlDecodea ("xxx", järjestelmän konfiguroinnin koodaus) kerran, Kutsut siis HttpUtility.UrlEncodea ("xxx", järjestelmän määrittämä koodaus) uudelleen palataksesi alkuperäiseen urt-8-koodausparametriin
Sitten käytä HttpUtility.UrlDecode("xxx", utf-8) purkaaksesi sen. merkkijono aaa = pyyntö. Request.QueryString["admin"]; Asunnonomistaja string a1 = HttpUtility.UrlEncode(aaa, System.Text.Encoding.GetEncoding("GB2312")); merkkijono a2 = HttpUtility.UrlDecode(a1,System.Text.Encoding.UTF8);
|