Acest articol este un articol oglindă al traducerii automate, vă rugăm să faceți clic aici pentru a sări la articolul original.

Vedere: 23136|Răspunde: 0

[Sursă] Cererea c# primește caractere distorsionate pentru parametri

[Copiază linkul]
Postat pe 25.12.2015 18:41:49 | | | |


În această dimineață am primit o întrebare de la un coleg: am spus că parametrii primiți sunt distorsionați, lasă-mă să ajut la rezolvarea problemei.


Platforma de care este responsabil colegul meu este construită Ext.js framework, iar fișierul de configurare web.config este configurat cu codificarea globală "GB2312":

<globalization requestEncoding="gb2312" responseEncoding="gb2312" fileEncoding="gb2312" culture="zh-CN"/>

Când frontend-ul trimite "textul chinezesc", backend-ul primește caractere distorsionate cu Request.QueryString["xxx"].

Indiferent cum decodezi cu System.Web.HttpUtility.UrlDecode("xxx", "encoding type"), nu funcționează.

Descrierea principiului:
1: Primul lucru de stabilit este că atunci când parametrii URL ai clientului sunt trimiși, Ext.js îi va codifica înainte de a-i trimite, iar codarea clientului este implicită UTF-8


2: Atunci de ce este distorsionat când primești parametri cu Request.QueryString["xxx"]?

Inversăm compilația pas cu pas,
2.1: Uită-te la codul proprietății QueryString:

  1. Code highlighting produced by Actipro CodeHighlighter (freeware)http://www.CodeHighlighter.com/-->public NameValueCollection QueryString
  2. {
  3.     get
  4.     {
  5.         if (this._queryString == null)
  6.         {
  7.             this._queryString = new HttpValueCollection();
  8.             if (this._wr != null)
  9.             {
  10.                 this.FillInQueryStringCollection();//重点代码切入点
  11.             }
  12.             this._queryString.MakeReadOnly();
  13.         }
  14.         if (this._flags[1])
  15.         {
  16.             this._flags.Clear(1);
  17.             ValidateNameValueCollection(this._queryString, "Request.QueryString");
  18.         }
  19.         return this._queryString;
  20.     }
  21. }
Cod de copiere

2.2: Decupare în metoda FillInQueryStringCollection()

  1. Code highlighting produced by Actipro CodeHighlighter (freeware)http://www.CodeHighlighter.com/-->private void FillInQueryStringCollection()
  2. {
  3.     byte[] queryStringBytes = this.QueryStringBytes;
  4.     if (queryStringBytes != null)
  5.     {
  6.         if (queryStringBytes.Length != 0)
  7.         {
  8.             this._queryString.FillFromEncodedBytes(queryStringBytes, this.QueryStringEncoding);
  9.         }
  10.     }//上面是对流字节的处理,即文件上传之类的。
  11.     else if (!string.IsNullOrEmpty(this.QueryStringText))
  12.     {
  13.         //下面这句是对普通文件提交的处理:FillFromString是个切入点,编码切入点是:this.QueryStringEncoding
  14.         this._queryString.FillFromString(this.QueryStringText, true, this.QueryStringEncoding);
  15.         
  16.     }
  17. }
Cod de copiere

2.3: Cut: QueryStringEncoding

  1. Code highlighting produced by Actipro CodeHighlighter (freeware)http://www.CodeHighlighter.com/-->internal Encoding QueryStringEncoding
  2. {
  3.     get
  4.     {
  5.         Encoding contentEncoding = this.ContentEncoding;
  6.         if (!contentEncoding.Equals(Encoding.Unicode))
  7.         {
  8.             return contentEncoding;
  9.         }
  10.         return Encoding.UTF8;
  11.     }
  12. }
  13. //点击进入this.ContentEncoding则为:
  14. public Encoding ContentEncoding
  15. {
  16.     get
  17.     {
  18.         if (!this._flags[0x20] || (this._encoding == null))
  19.         {
  20.             this._encoding = this.GetEncodingFromHeaders();
  21.             if (this._encoding == null)
  22.             {
  23.                 GlobalizationSection globalization = RuntimeConfig.GetLKGConfig(this._context).Globalization;
  24.                 this._encoding = globalization.RequestEncoding;
  25.             }
  26.             this._flags.Set(0x20);
  27.         }
  28.         return this._encoding;
  29.     }
  30.     set
  31.     {
  32.         this._encoding = value;
  33.         this._flags.Set(0x20);
  34.     }
  35. }
Cod de copiere
Din codul QueryStringEncoding, sistemul folosește implicit metoda de codare a nodului de configurare a globalizării, iar dacă nu, implicit este codarea UTF-8
2.4: Tăie în FillFromString(string s, bool urlencoded, codare Encoding)

  1. 代码有点长,就折叠起来了

  2. Code highlighting produced by Actipro CodeHighlighter (freeware)http://www.CodeHighlighter.com/-->internal void FillFromString(string s, bool urlencoded, Encoding encoding)
  3. {
  4.     int num = (s != null) ? s.Length : 0;
  5.     for (int i = 0; i < num; i++)
  6.     {
  7.         int startIndex = i;
  8.         int num4 = -1;
  9.         while (i < num)
  10.         {
  11.             char ch = s[i];
  12.             if (ch == '=')
  13.             {
  14.                 if (num4 < 0)
  15.                 {
  16.                     num4 = i;
  17.                 }
  18.             }
  19.             else if (ch == '&')
  20.             {
  21.                 break;
  22.             }
  23.             i++;
  24.         }
  25.         string str = null;
  26.         string str2 = null;
  27.         if (num4 >= 0)
  28.         {
  29.             str = s.Substring(startIndex, num4 - startIndex);
  30.             str2 = s.Substring(num4 + 1, (i - num4) - 1);
  31.         }
  32.         else
  33.         {
  34.             str2 = s.Substring(startIndex, i - startIndex);
  35.         }
  36.         if (urlencoded)//外面的传值默认是true,所以会执行以下语句
  37.         {
  38.             base.Add(HttpUtility.UrlDecode(str, encoding), HttpUtility.UrlDecode(str2, encoding));
  39.         }
  40.         else
  41.         {
  42.             base.Add(str, str2);
  43.         }
  44.         if ((i == (num - 1)) && (s[i] == '&'))
  45.         {
  46.             base.Add(null, string.Empty);
  47.         }
  48.     }
  49. }
Cod de copiere
Din acest punct constatăm că toate intrările parametrilor sunt numite o singură dată: HttpUtility.UrlDecode(str2, codificare);

Când clientul js trimite chineză serverului prin codare utf-8, când îl primește cu Request.QueryString, îl va decoda mai întâi o dată cu gb2312 configurat prin globalizare, rezultând caractere distorsionate.

1: Metoda de codare JS este URT-8

2: Partea serverului a configurat implicit GB2312

3: Request.QueryString va apela implicit HttpUtility.UrlDecode pentru a decoda parametrii primiți prin codificarea configurării sistemului.

1: Sistemul selectează codificarea implicită în următoarea ordine: antet de cerere http - >nod de configurare globalizare - implicit UTF-8

2: Când introduci URL-ul direct în chineză, diferite browsere pot gestiona diferit, de exemplu: IE nu codifică și trimite direct, Firefox trimite URL-ul după codificarea GB2312.

3: Pentru "caractere chinezești" necodificate, după folosirea apelului intern Request.QueryString HttpUtility.UrlDecode, de gb2312->utf-8,

Dacă caracterul chinezesc nu este găsit, acesta va fi convertit implicit în "%ufffd", rezultând caractere ireversibile și distorsionate.

4: Drumul spre rezolvare
Cunoscând principiul, există multe moduri de a o rezolva:
1: Unificarea globală este codificarea UTF-8, care economisește probleme și griji.

2: Când GB2312 este specificat global, URL-ul este chinezesc, iar js trebuie codificat, cum ar fi ext.js framework.

Astfel, poți gestiona doar în mod special, specificând codarea și decodarea pe partea de server.
Pentru că sistemul implicit apelează HttpUtility.UrlDecode("xxx", codificarea configurației sistemului) o dată,
Așadar, apelezi din nou la HttpUtility.UrlEncode("xxx", codarea configurată de sistem) pentru a reveni la parametrul original de codare urt-8

Apoi folosește HttpUtility.UrlDecode("xxx", utf-8) pentru a-l decoda.
Șirul AAA = Cerere. Request.QueryString["admin"];    Proprietar
                            string a1 = HttpUtility.UrlEncode(aaa, System.Text.Encoding.GetEncoding("GB2312"));
                            șirul a2 = HttpUtility.UrlDecode(a1,System.Text.Encoding.UTF8);








Precedent:Salut
Următor:Ce algoritm, sunt deprimat de câteva zile.
Disclaimer:
Tot software-ul, materialele de programare sau articolele publicate de Code Farmer Network sunt destinate exclusiv scopurilor de învățare și cercetare; Conținutul de mai sus nu va fi folosit în scopuri comerciale sau ilegale, altfel utilizatorii vor suporta toate consecințele. Informațiile de pe acest site provin de pe Internet, iar disputele privind drepturile de autor nu au legătură cu acest site. Trebuie să ștergi complet conținutul de mai sus de pe calculatorul tău în termen de 24 de ore de la descărcare. Dacă îți place programul, te rugăm să susții software-ul autentic, să cumperi înregistrarea și să primești servicii autentice mai bune. Dacă există vreo încălcare, vă rugăm să ne contactați prin e-mail.

Mail To:help@itsvse.com