Vanmorgen kreeg ik een vraag van een collega: ik zei dat de ontvangen parameters verward waren, laat mij helpen om het op te lossen.
Het platform waarvoor mijn collega verantwoordelijk is, is gebouwd Ext.js framework, en het web.config-configuratiebestand is geconfigureerd met de globale "GB2312"-codering:
<globalization requestEncoding="gb2312" responseEncoding="gb2312" fileCodering="gb2312" culture="zh-CN"/>
Wanneer de frontend de "Chinese tekst" indient, ontvangt de backend vervormde tekens met Request.QueryString["xxx"].
Hoe je ook decodert met System.Web.HttpUtility.UrlDecode("xxx", "encoding type"), het werkt niet.
Hoofdbeschrijving: 1: Het eerste wat vastgesteld moet worden is dat wanneer de URL-parameters van de client worden ingediend, Ext.js deze codeert voordat hij ze indient, en de codering van de client standaard UTF-8 codering is
2: Waarom is het dan verward bij het ontvangen van parameters met Request.QueryString["xxx"]?
We draaien de compilatie stap voor stap om, 2.1: Kijk naar de code voor de eigenschap 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;
- }
- }
Code kopiëren
2.2: Snijden in de FillInQueryStringCollection()-methode
- 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);
-
- }
- }
Code kopiëren
2.3: Cut: 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);
- }
- }
Code kopiërenUit de QueryStringEncoding-code schakelt het systeem standaard over op de coderingsmethode van de globalisatieconfiguratie-node, en als dat niet zo is, is de standaard UTF-8-codering 2.4: Snijden in FillFromString (string s, bool urlencoded, codering coderen)
- 代码有点长,就折叠起来了
- 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);
- }
- }
- }
Code kopiërenVanaf dit punt zien we dat alle parameterinvoer één keer worden aangeroepen: HttpUtility.UrlDecode(str2, encoding);
Wanneer client js Chinees indient aan de server in utf-8-codering, zal het bij ontvangst met Request.QueryString deze eerst één keer decoderen met gb2312 geconfigureerd door globalisering, wat resulteert in vervormde tekens.
1: De JS-coderingsmethode is URT-8
2: De serverzijde heeft de standaard ingesteld op GB2312
3: Request.QueryString roept standaard HttpUtility.UrlDecode aan om de ontvangen parameters te decoderen met systeemconfiguratiecodering.
1: Het systeem selecteert de standaardcodering in de volgende volgorde: http request header - >globalization configuration node - default UTF-8
2: Bij het direct invoeren van de URL in het Chinees kunnen verschillende browsers dit anders behandelen, bijvoorbeeld: IE codeert niet en stuurt het direct in, Firefox dient de URL in na de GB2312-codering.
3: Voor niet-gecodeerde "Chinese karakters", na gebruik van de interne aanroep HttpUtility.UrlDecode, na gebruik van de interne aanroep van Request.QueryString, door gb2312->utf-8,
Als het Chinese teken niet wordt gevonden, wordt het standaard omgezet naar "%ufffd", wat resulteert in onomkeerbare vervormde tekens.
4: De weg naar een oplossing Als je het principe kent, zijn er veel manieren om het op te lossen: 1: De wereldwijde unificatie is UTF-8-codering, wat problemen en zorgen bespaart.
2: Wanneer GB2312 globaal wordt gespecificeerd, is de url Chinees en moet js worden gecodeerd, zoals ext.js framework.
Op deze manier kun je het alleen specifiek afhandelen, waarbij je de codering en decodering aan de serverzijde specificeert. Omdat het standaardsysteem HttpUtility.UrlDecode("xxx", de codering van de systeemconfiguratie) één keer aanroept, Dus roep je HttpUtility.UrlEncode("xxx", de codering die door het systeem is geconfigureerd) opnieuw aan om terug te keren naar de oorspronkelijke urt-8 coderingsparameter
Gebruik vervolgens HttpUtility.UrlDecode("xxx", utf-8) om het te decoderen. string aaa = verzoek. Request.QueryString["admin"]; Huiseigenaar string a1 = HttpUtility.UrlEncode(aaa, System.Text.Encoding.GetEncoding("GB2312")); string a2 = HttpUtility.UrlDecode(a1,System.Text.Encoding.UTF8);
|