Αυτό το άρθρο είναι ένα άρθρο καθρέφτη της αυτόματης μετάφρασης, κάντε κλικ εδώ για να μεταβείτε στο αρχικό άρθρο.

Άποψη: 23136|Απάντηση: 0

[Πηγή] c# Το αίτημα λαμβάνει αλλοιωμένους χαρακτήρες για παραμέτρους

[Αντιγραφή συνδέσμου]
Δημοσιεύτηκε στις 25/12/2015 6:41:49 μ.μ. | | | |


Σήμερα το πρωί μου έκανε μια ερώτηση ένας συνάδελφος: Είπα ότι οι παράμετροι που ελήφθησαν ήταν αλλοιωμένες, επιτρέψτε μου να βοηθήσω στην επίλυσή του.


Η πλατφόρμα για την οποία είναι υπεύθυνος ο συνάδελφός μου είναι χτισμένη Ext.js πλαίσιο και το αρχείο διαμόρφωσης web.config έχει διαμορφωθεί με την καθολική κωδικοποίηση "GB2312":

<αίτημα παγκοσμιοποίησηςEncoding="gb2312" responseEncoding="gb2312" fileEncoding="gb2312" culture="zh-CN"/>

Όταν το frontend υποβάλλει το "Κινεζικό κείμενο", το backend λαμβάνει αλλοιωμένους χαρακτήρες με Request.QueryString["xxx"].

Ανεξάρτητα από το πώς αποκωδικοποιείτε με το System.Web.HttpUtility.UrlDecode("xxx", "τύπος κωδικοποίησης"), δεν λειτουργεί.

Περιγραφή αρχής:
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, κωδικοποίηση);

Όταν το client js υποβάλλει κινέζικα στον διακομιστή σε κωδικοποίηση utf-8, όταν το λαμβάνει με το Request.QueryString, θα το αποκωδικοποιήσει πρώτα μία φορά με το gb2312 που έχει διαμορφωθεί από την παγκοσμιοποίηση, με αποτέλεσμα αλλοιωμένους χαρακτήρες.

1: Η μέθοδος κωδικοποίησης JS είναι URT-8

2: Η πλευρά του διακομιστή έχει διαμορφώσει την προεπιλογή σε GB2312

3: Το Request.QueryString θα καλέσει το HttpUtility.UrlDecode από προεπιλογή για να αποκωδικοποιήσει τις ληφθείσες παραμέτρους με κωδικοποίηση ρύθμισης παραμέτρων συστήματος.

1: Το σύστημα επιλέγει την προεπιλεγμένη κωδικοποίηση με την ακόλουθη σειρά: κεφαλίδα αιτήματος http - κόμβος διαμόρφωσης >globalization - προεπιλεγμένο 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 πλαίσιο.

Με αυτόν τον τρόπο, μπορείτε να το χειριστείτε μόνο ειδικά, καθορίζοντας την κωδικοποίηση και την αποκωδικοποίηση από την πλευρά του διακομιστή.
Επειδή το προεπιλεγμένο σύστημα καλεί το HttpUtility.UrlDecode ("xxx", την κωδικοποίηση της διαμόρφωσης του συστήματος) μία φορά,
Έτσι, καλείτε ξανά το HttpUtility.UrlEncode("xxx", την κωδικοποίηση που έχει διαμορφωθεί από το σύστημα) για να επιστρέψετε στην αρχική παράμετρο κωδικοποίησης urt-8

Στη συνέχεια, χρησιμοποιήστε το HttpUtility.UrlDecode("xxx", utf-8) για να το αποκωδικοποιήσετε.
συμβολοσειρά aaa = αίτημα. Request.QueryString["admin"];    Ιδιοκτήτης σπιτιού
                            συμβολοσειρά a1 = HttpUtility.UrlEncode(aaa, System.Text.Encoding.GetEncoding("GB2312"));
                            συμβολοσειρά a2 = HttpUtility.UrlDecode(a1,System.Text.Encoding.UTF8);








Προηγούμενος:Γεια σου
Επόμενος:Τι αλγόριθμος, έχω κατάθλιψη εδώ και αρκετές μέρες.
Αποκήρυξη:
Όλο το λογισμικό, το υλικό προγραμματισμού ή τα άρθρα που δημοσιεύονται από το Code Farmer Network προορίζονται μόνο για μαθησιακούς και ερευνητικούς σκοπούς. Το παραπάνω περιεχόμενο δεν θα χρησιμοποιηθεί για εμπορικούς ή παράνομους σκοπούς, άλλως οι χρήστες θα υποστούν όλες τις συνέπειες. Οι πληροφορίες σε αυτόν τον ιστότοπο προέρχονται από το Διαδίκτυο και οι διαφορές πνευματικών δικαιωμάτων δεν έχουν καμία σχέση με αυτόν τον ιστότοπο. Πρέπει να διαγράψετε εντελώς το παραπάνω περιεχόμενο από τον υπολογιστή σας εντός 24 ωρών από τη λήψη. Εάν σας αρέσει το πρόγραμμα, υποστηρίξτε γνήσιο λογισμικό, αγοράστε εγγραφή και λάβετε καλύτερες γνήσιες υπηρεσίες. Εάν υπάρχει οποιαδήποτε παραβίαση, επικοινωνήστε μαζί μας μέσω email.

Mail To:help@itsvse.com