I morges ble jeg stilt et spørsmål av en kollega: Jeg sa at parameterne som ble mottatt var uforståelige, la meg hjelpe til med å løse det.
Plattformen kollegaen min har ansvar for er bygget Ext.js rammeverk, og web.config-konfigurasjonsfilen er konfigurert med den globale "GB2312"-kodingen:
<globaliseringsforespørselKoding="gb2312" svarKoding="gb2312" filKoding="gb2312" culture="zh-CN"/>
Når frontenden sender inn «kinesisk tekst», mottar backenden forvrengte tegn med Request.QueryString["xxx"].
Uansett hvordan du dekodes med System.Web.HttpUtility.UrlDecode("xxx", "encoding type"), fungerer det ikke.
Hovedbeskrivelse: 1: Det første som må avgjøres er at når klientens URL-parametere sendes inn, vil Ext.js kode dem før de sendes inn, og klientens koding er som standard UTF-8-koding
2: Hvorfor er det da utydelig når man mottar parametere med Request.QueryString["xxx"]?
Vi reverserer kompileringen steg for steg, 2.1: Se på koden for QueryString-egenskapen:
- 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;
- }
- }
Kopier koden
2.2: Kutt inn i FillInQueryStringCollection()-metoden
- 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);
-
- }
- }
Kopier koden
2.3: Kutt: 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);
- }
- }
Kopier kodenFra QueryStringEncoding-koden går systemet som standard over til kodingsmetoden til globaliseringskonfigurasjonsnoden, og hvis ikke, er standarden UTF-8-koding 2.4: Kutt i FillFromString (streng s, bool urlencoded, koding av koding)
- 代码有点长,就折叠起来了
- 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);
- }
- }
- }
Kopier kodenFra dette punktet finner vi at alle parameterinnganger kalles én gang: HttpUtility.UrlDecode(str2, koding);
Når klient js sender kinesisk til serveren i utf-8-koding, vil den først dekode det én gang med gb2312 konfigurert ved globalisering, noe som resulterer i utydelige tegn.
1: JS-kodingsmetoden er URT-8
2: Serversiden har konfigurert standardinnstillingen til GB2312
3: Request.QueryString vil som standard kalle HttpUtility.UrlDecode for å dekode mottatte parametere med systemkonfigurasjonskoding.
1: Systemet velger standardkodingen i følgende rekkefølge: http forespørselshode - >globaliseringskonfigurasjonsnode - standard UTF-8
2: Når URL-en legges direkte inn på kinesisk, kan ulike nettlesere håndtere det forskjellig, for eksempel: IE koder ikke og sender inn direkte, Firefox sender inn URL-en etter GB2312-kodingen.
3: For ukodede "kinesiske tegn", etter bruk av Request.QueryString internt kall HttpUtility.UrlDecode, av gb2312->utf-8,
Hvis det kinesiske tegnet ikke blir funnet, vil det som standard bli konvertert til "%ufffd", noe som resulterer i irreversible utydelige tegn.
4: Veien til løsning Når man kjenner prinsippet, finnes det mange måter å løse det på: 1: Den globale samlingen er UTF-8-koding, som sparer for problemer og bekymringer.
2: Når GB2312 er globalt spesifisert, er url-en kinesisk, og js må kodes, slik som ext.js rammeverk.
På denne måten kan du bare håndtere det spesielt, ved å spesifisere koding og dekoding på serversiden. Fordi standardsystemet kaller HttpUtility.UrlDecode("xxx", kodingen av systemkonfigurasjonen) én gang, Så du kaller HttpUtility.UrlEncode("xxx", kodingen konfigurert av systemet) igjen for å returnere til den opprinnelige urt-8-kodingsparameteren
Bruk deretter HttpUtility.UrlDecode("xxx", utf-8) for å dekode den. streng aaa = forespørsel. Request.QueryString["admin"]; Huseier streng a1 = HttpUtility.UrlEncode(aaa, System.Text.Encoding.GetEncoding("GB2312")); string a2 = HttpUtility.UrlDecode(a1,System.Text.Encoding.UTF8);
|