Тази статия е огледална статия за машинен превод, моля, кликнете тук, за да преминете към оригиналната статия.

Изглед: 23136|Отговор: 0

[Източник] c# Request получава изкривени символи за параметри

[Копирай линк]
Публикувано в 25.12.2015 г. 18:41:49 ч. | | | |


Тази сутрин колега ми зададе въпрос: казах, че получените параметри са объркани, нека помогна да се реши.


Платформата, за която отговаря колегата ми, е изградена Ext.js фреймуърк, а конфигурационният файл web.config е конфигуриран с глобалното кодиране "GB2312":

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

Когато фронтендът изпрати "китайски текст", бекендът получава изкривени знаци с Request.QueryString["xxx"].

Без значение как декодирате с System.Web.HttpUtility.UrlDecode("xxx", "encoding type"), не работи.

Описание на принципа:
1: Първото нещо, което трябва да се определи, е че когато се подадат URL параметрите на клиента, Ext.js ги кодира преди да ги изпратят, а кодирането на клиента по подразбиране е UTF-8


2: Тогава защо е объркан при получаване на параметри с Request.QueryString["xxx"]?

Обръщаме компилацията стъпка по стъпка,
2.1: Погледнете кода за свойството 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. }
Копирай код

2.2: Изрязване към метода 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. }
Копирай код

2.3: Изрязване: 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. }
Копирай код
От кода QueryStringEncoding системата по подразбиране използва метода на кодиране на глобализационния конфигурационен възел, а ако не, по подразбиране кодирането е UTF-8
2.4: Разрязване на FillFromString (низ s, bool urlencoded, кодиране на кодиране)

  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. }
Копирай код
От тази точка откриваме, че всички входове на параметри се извикват веднъж: HttpUtility.UrlDecode(str2, кодиране);

Когато клиентът js изпраща китайски език на сървъра в utf-8 кодиране, когато го получава с Request.QueryString, първо го декодира веднъж с gb2312, конфигуриран чрез глобализация, което води до изкривени знаци.

1: JS методът за кодиране е URT-8

2: Сървърната страна е конфигурирала по подразбиране GB2312

3: Request.QueryString по подразбиране извиква HttpUtility.UrlDecode, за да декодира получените параметри с кодиране на системната конфигурация.

1: Системата избира стандартното кодиране в следния ред: http request header - >globalization configuration node - default UTF-8

2: При въвеждане на URL адреса директно на китайски, различните браузъри могат да го обработват по различен начин, например: IE не кодира и изпраща директно, Firefox подава URL адреса след кодиране на GB2312.

3: За некодирани "китайски знаци", след използване на вътрешното извикване на Request.QueryString HttpUtility.UrlDecode, чрез gb2312->utf-8,

Ако китайският знак не бъде намерен, той по подразбиране ще бъде конвертиран в "%ufffd", което води до необратими изкривени знаци.

4: Пътят към разрешаването
Познавайки принципа, има много начини да се реши:
1: Глобалното обединение е UTF-8 кодиране, което спестява неудобства и тревоги.

2: Когато GB2312 е глобално зададен, URL-то е китайски, а js трябва да бъде кодиран, като ext.js framework.

По този начин можеш да го обработиш само специално, като специфицираш кодирането и декодирането от страна на сървъра.
Тъй като по подразбиране системата извиква HttpUtility.UrlDecode("xxx", кодирането на конфигурацията на системата) веднъж,
Затова отново извикваш HttpUtility.UrlEncode("xxx", кодирането, конфигурирано от системата), за да се върнеш към оригиналния параметър urt-8

След това използвайте HttpUtility.UrlDecode("xxx", utf-8), за да го декодирате.
Низ AAA = заявка. Request.QueryString["admin"];    Собственик на жилище
                            string a1 = HttpUtility.UrlEncode(aaa, System.Text.Encoding.GetEncoding("GB2312"));
                            низ a2 = HttpUtility.UrlDecode(a1,System.Text.Encoding.UTF8);








Предишен:Здравей
Следващ:Какъв алгоритъм, депресиран съм от няколко дни.
Отричане:
Целият софтуер, програмни материали или статии, публикувани от Code Farmer Network, са само за учебни и изследователски цели; Горното съдържание не трябва да се използва за търговски или незаконни цели, в противен случай потребителите ще понесат всички последствия. Информацията на този сайт идва от интернет, а споровете за авторски права нямат нищо общо с този сайт. Трябва напълно да изтриете горното съдържание от компютъра си в рамките на 24 часа след изтеглянето. Ако ви харесва програмата, моля, подкрепете оригинален софтуер, купете регистрация и получете по-добри услуги. Ако има нарушение, моля, свържете се с нас по имейл.

Mail To:help@itsvse.com