Este artículo es un artículo espejo de traducción automática, por favor haga clic aquí para saltar al artículo original.

Vista: 23136|Respuesta: 0

[Fuente] La petición c# recibe caracteres distorsionados para los parámetros

[Copiar enlace]
Publicado en 25/12/2015 18:41:49 | | | |


Esta mañana un compañero me hizo una pregunta: dije que los parámetros recibidos estaban distorsionados, que me ayudara a resolverlo.


La plataforma de la que es responsable mi compañero está construida Ext.js framework, y el archivo de configuración web.config está configurado con la codificación global "GB2312":

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

Cuando el frontend envía el "texto chino", recibe caracteres distorsionados con Request.QueryString["xxx"].

No importa cómo decodifices con System.Web.HttpUtility.UrlDecode("xxx", "encoding type"), no funciona.

Descripción del principio:
1: Lo primero que hay que determinar es que cuando se envían los parámetros de URL del cliente, Ext.js los codificará antes de enviarlos, y la codificación del cliente es por defecto UTF-8


2: Entonces, ¿por qué se distorsiona al recibir parámetros con Request.QueryString["xxx"]?

Invertimos la compilación paso a paso,
2.1: Mira el código de la propiedad 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. }
Copiar código

2.2: Cortar en el método 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. }
Copiar código

2.3: Corte: 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. }
Copiar código
Según el código QueryStringEncoding, el sistema utiliza por defecto el método de codificación del nodo de configuración de globalización, y si no, el método por defecto es la codificación UTF-8
2.4: Cortar en FillFromString (cadenas s, bool urlencoded, codificación de codificación)

  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. }
Copiar código
A partir de este punto vemos que todas las entradas de parámetros se llaman una vez: HttpUtility.UrlDecode(str2, codificación);

Cuando el js del cliente envía chino al servidor en codificación utf-8, al recibirlo con Request.QueryString, primero lo decodifica una vez con gb2312 configurado por globalización, resultando en caracteres distorsionados.

1: El método de codificación JS es URT-8

2: El lado servidor ha configurado el predeterminado en GB2312

3: Request.QueryString llamará por defecto a HttpUtility.UrlDecode para decodificar los parámetros recibidos mediante la codificación de configuración del sistema.

1: El sistema selecciona la codificación predeterminada en el siguiente orden: cabecera de solicitud http - nodo de configuración >globalización - UTF-8 por defecto

2: Al introducir la URL directamente en chino, diferentes navegadores pueden manejarla de forma distinta, por ejemplo: IE no codifica y se envía directamente, Firefox envía la URL después de la codificación GB2312.

3: Para "caracteres chinos" no codificados, tras usar la llamada interna Request.QueryString HttpUtility.UrlDecode, por gb2312->utf-8,

Si no se encuentra el carácter chino, se convertirá por defecto en "%ufffd", resultando en caracteres distorsionados irreversibles.

4: El camino hacia la resolución
Conociendo el principio, hay muchas formas de solucionarlo:
1: La unificación global es la codificación UTF-8, que ahorra problemas y preocupaciones.

2: Cuando GB2312 está especificado globalmente, la URL es china y JS debe codificarse, como ext.js framework.

De este modo, solo puedes manejarlo de forma especial, especificando la codificación y decodificación en el lado del servidor.
Porque el sistema por defecto llama a HttpUtility.UrlDecode("xxx", la codificación de la configuración del sistema) una vez,
Así que llamas de nuevo a HttpUtility.UrlEncode("xxx", la codificación configurada por el sistema) para volver al parámetro original de codificación urt-8

Luego usa HttpUtility.UrlDecode("xxx", utf-8) para decodificarlo.
cadena AAA = solicitud. Request.QueryString["admin"];    Propietario
                            cadena a1 = HttpUtility.UrlEncode(aaa, System.Text.Encoding.GetEncoding("GB2312"));
                            cadena a2 = HttpUtility.UrlDecode(a1,System.Text.Encoding.UTF8);








Anterior:hola
Próximo:Vaya algoritmo, llevo varios días deprimido.
Renuncia:
Todo el software, materiales de programación o artículos publicados por Code Farmer Network son únicamente para fines de aprendizaje e investigación; El contenido anterior no se utilizará con fines comerciales o ilegales; de lo contrario, los usuarios asumirán todas las consecuencias. La información de este sitio proviene de Internet, y las disputas de derechos de autor no tienen nada que ver con este sitio. Debes eliminar completamente el contenido anterior de tu ordenador en un plazo de 24 horas desde la descarga. Si te gusta el programa, por favor apoya el software genuino, compra el registro y obtén mejores servicios genuinos. Si hay alguna infracción, por favor contáctanos por correo electrónico.

Mail To:help@itsvse.com