Questa mattina un collega mi ha fatto una domanda: ho detto che i parametri ricevuti erano confusi, lasciate che io aiuti a risolverli.
La piattaforma di cui il mio collega è responsabile è costruita Ext.js framework, e il file di configurazione web.config è configurato con la codifica globale "GB2312":
<globalization requestEncoding="gb2312" responseEncoding="gb2312" fileEncoding="gb2312" culture="zh-CN"/>
Quando il frontend invia il "testo cinese", il backend riceve caratteri distorti con Request.QueryString["xxx"].
Non importa come decodi con System.Web.HttpUtility.UrlDecode("xxx", "encoding type"), non funziona.
Descrizione del principio: 1: La prima cosa da determinare è che quando vengono inviati i parametri URL del client, Ext.js li codifica prima di inviarli, e la codifica del client è di default UTF-8
2: Allora perché è distorto quando ricevono parametri con Request.QueryString["xxx"]?
Invertiamo la compilazione passo dopo passo, 2.1: Guarda il codice per la proprietà QueryString:
- 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;
- }
- }
Copia codice
2.2: Tagliare nel metodo FillInQueryStringCollection()
- 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);
-
- }
- }
Copia codice
2.3: Taglio: 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);
- }
- }
Copia codiceDal codice QueryStringEncoding, il sistema predefinito utilizza il metodo di codifica del nodo di configurazione globalizzazione e, in caso contrario, il metodo predefinito è la codifica UTF-8 2.4: Taglia in FillFromString(stringa s, bool urlencod, codifica codifica)
- 代码有点长,就折叠起来了
- 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);
- }
- }
- }
Copia codiceDa questo punto si scopre che tutti gli input dei parametri vengono chiamati una sola volta: HttpUtility.UrlDecode(str2, codifica);
Quando il client js invia il cinese al server con la codifica utf-8, ricevendolo con Request.QueryString, lo decodifica prima una volta con gb2312 configurato tramite globalizzazione, risultando in caratteri distorti.
1: Il metodo di codifica JS è URT-8
2: Il lato server ha configurato il default su GB2312
3: Request.QueryString chiamerà di default HttpUtility.UrlDecode per decodificare i parametri ricevuti con la codifica di configurazione di sistema.
1: Il sistema seleziona la codifica predefinita nel seguente ordine: intestazione richiesta http - nodo di configurazione >globalizzazione - UTF-8 predefinito
2: Quando si inserisce l'URL direttamente in cinese, browser diversi possono gestirlo in modo differente, ad esempio: IE non codifica e invia direttamente, Firefox invia l'URL dopo la codifica GB2312.
3: Per "caratteri cinesi" non codificati, dopo aver usato Request.QueryString chiama internamente HttpUtility.UrlDecode, tramite gb2312->utf-8,
Se il carattere cinese non viene trovato, verrà convertito di default in "%ufffd", risultando in caratteri irreversibili e distorti.
4: La strada verso la risoluzione Conoscendo il principio, ci sono molti modi per risolverlo: 1: L'unificazione globale è la codifica UTF-8, che evita problemi e preoccupazioni.
2: Quando GB2312 è specificato globalmente, l'URL è cinese e js deve essere codificato, come ext.js framework.
In questo modo, puoi gestirlo solo in modo specifico, specificando la codifica e la decodifica lato server. Poiché il sistema predefinito chiama HttpUtility.UrlDecode("xxx", la codifica della configurazione di sistema) una volta, Quindi richiami HttpUtility.UrlEncode("xxx", la codifica configurata dal sistema) per tornare al parametro di codifica urt-8 originale
Poi usa HttpUtility.UrlDecode("xxx", utf-8) per decodificarlo. stringa aaa = richiesta. Request.QueryString["admin"]; Proprietario di casa stringa a1 = HttpUtility.UrlEncode(aaa, System.Text.Encoding.GetEncoding("GB2312")); stringa a2 = HttpUtility.UrlDecode(a1,System.Text.Encoding.UTF8);
|