I morges blev jeg stillet et spørgsmål af en kollega: Jeg sagde, at de modtagne parametre var forvanskede, lad mig hjælpe med at løse det.
Platformen, som min kollega er ansvarlig for, er bygget Ext.js framework, og web.config-konfigurationsfilen er konfigureret med den globale "GB2312"-kodning:
<globalization requestEncoding="gb2312" responseEncoding="gb2312" fileCoding="gb2312" culture="zh-CN"/>
Når frontenden indsender den "kinesiske tekst", modtager backenden forvrængede tegn med Request.QueryString["xxx"].
Uanset hvordan du dekoder med System.Web.HttpUtility.UrlDecode("xxx", "encoding type"), virker det ikke.
Hovedbeskrivelse: 1: Det første, der skal afgøres, er, at når klientens URL-parametre indsendes, vil Ext.js kode dem, før de indsendes, og klientens kodning er som standard UTF-8-kodning
2: Hvorfor er det så forvrænget, når man modtager parametre med Request.QueryString["xxx"]?
Vi vender kompileringen trin for trin, 2.1: Se på koden for QueryString-egenskaben:
- 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 kode
2.2: Skærer ind 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 kode
2.3: Klip: 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 kodeFra QueryStringEncoding-koden vælger systemet som standard globaliseringskonfigurationsnodens kodningsmetode, og hvis ikke, er standarden UTF-8-kodning 2.4: Klip i FillFromString (streng s, bool urlencoded, kodning koder)
- 代码有点长,就折叠起来了
- 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 kodeHerfra finder vi, at alle parameterinput kaldes én gang: HttpUtility.UrlDecode(str2, kodning);
Når klient js indsender kinesisk til serveren i utf-8-kodning, vil den først dekode den én gang med gb2312 konfigureret ved globalisering, når den modtager den med Request.QueryString.
1: JS-kodningsmetoden er URT-8
2: Serversiden har konfigureret standardindstillingen til GB2312
3: Request.QueryString kalder HttpUtility.UrlDecode som standard for at dekode de modtagne parametre med systemkonfigurationskodning.
1: Systemet vælger standardkodningen i følgende rækkefølge: http anmodningsheader - >globaliseringskonfigurationsnode - standard UTF-8
2: Når URL'en indtastes direkte til kinesisk, kan forskellige browsere håndtere det forskelligt, for eksempel: IE koder ikke og indsender direkte, Firefox indsender URL'en efter GB2312-kodningen.
3: For ukodede "kinesiske tegn", efter brug af Request.QueryString internt kald HttpUtility.UrlDecode, af gb2312->utf-8,
Hvis det kinesiske tegn ikke findes, vil det som standard blive konverteret til "%ufffd", hvilket resulterer i irreversible forvrængede tegn.
4: Vejen til løsning Med kendskab til princippet er der mange måder at løse det på: 1: Den globale forening er UTF-8-kodning, som sparer besvær og bekymring.
2: Når GB2312 er globalt specificeret, er url'en kinesisk, og js skal kodes, som ext.js framework.
På denne måde kan du kun håndtere det specielt, ved at specificere kodning og dekodning på serversiden. Fordi standardsystemet kalder HttpUtility.UrlDecode("xxx", kodningen af systemkonfigurationen) én gang, Så kalder du HttpUtility.UrlEncode("xxx", kodningen konfigureret af systemet) igen for at vende tilbage til den oprindelige urt-8 kodningsparameter
Brug derefter HttpUtility.UrlDecode("xxx", utf-8) til at dekode det. streng AAA = anmodning. Request.QueryString["admin"]; Boligejer string a1 = HttpUtility.UrlEncode(aaa, System.Text.Encoding.GetEncoding("GB2312")); streng a2 = HttpUtility.UrlDecode(a1,System.Text.Encoding.UTF8);
|