經過前面兩篇《Request 接收參數亂碼原理解析一:服務器端解碼原理》和《Request 接收參數亂碼原理解析二:瀏覽器端編碼原理》,瞭解了服務器和瀏覽器編碼解碼的原理,接下來結合項目中遇到的具體問題,分析亂碼問題的解決方法。javascript
1.用戶身份驗證Cookie亂碼問題html
用戶登陸後,一般用Cookie記錄身份,如把用戶名記錄到Cookie中,其它頁面讀取Cookie,對Cookie值驗證,符合必定規則的話則認爲是合法用戶。java
protected void Page_Load(object sender, EventArgs e) { //假定登錄用戶名爲北京(歷史緣由系統容許有中文名) Response.Cookies["username"].Value = Server.UrlEncode("北京"); }
protected void Page_Load(object sender, EventArgs e) { //讀取Cookie,若是用戶名存在則認爲登錄成功(實際驗證比這要複雜不少) string userName = Server.UrlDecode(Request.Cookies["username"].Value); bool isLogin = userName == "北京"; Response.Write("用戶" + userName + "登錄" + (isLogin ? "成功" : "失敗")); }
由於用戶名存在中文問題,寫入編碼和讀取解碼都是在服務器端進行的,因此寫Cookie時將值用Server.UrlEncode()編碼,讀取Cookie值時用Server.UrlDecode()解碼,一般認爲這兩個函數是成對出現的,都是由web.config中的globalization結點指定的。web
這段代碼絕大部分運行是沒問題的,但遇到Post請求的AJax調用頁面時,就出錯了,獲得的username值是亂碼。經過前面兩篇的分析可知:Ajax請求時,頁面請求Header中加了「Content-Type: text/html; charset=utf8」,Server.UrlDecode()解碼方式變成了utf-8,亂碼天然產生了。問題解決方式是解碼時指定編碼方式,不要再用依賴於上下文的函數解碼了,能夠改成「HttpUtility.UrlDecode(Request.Cookies["username"].Value, System.Text.Encoding.GetEncoding("GB2312"))」。ajax
<form id="form1" runat="server"> <div> <input type="button" name="btnAjaxPost" value="AJax提交" onclick="Ajax()" /> <div id="divMessage" style="color: red"></div> </div> </form> <script type="text/javascript"> function Ajax() { $.ajax({ type: "POST", url: "LoginValidateCookie.aspx", data: { name: "name" }, success: function (data) { $("#divMessage").html(data); } }); } </script>
2.Url地址欄中的中文參數瀏覽器
有些頁面地址,因爲某些緣由帶了中文參數(如http://localhost:52443/Encode/EncodeTest.aspx?username=北京),而這些地址又可能已經被baidu等搜索引擎收錄,所以不能單靠生成新地址規則方式解決,項目必須作到兼容帶中文參數的地址。服務器
若是是相似示例中的邏輯,中文參數爲系統用戶的用戶名,則能夠採用先用Request.QueryString方式獲取,獲得username若是在系統中存在,則認爲獲得的參數是正確的;若是username在系統中不存在,則認爲多是由於參數中文亂碼緣由引發的,再用NameValueCollection方式獲取一次,解碼方式和系統解碼是不同的(系統配置的是GB2312,則指定用utf-8解)。ide
string username = Request.QueryString["username"]; //若是經過Request方式獲取參數亂碼,則能夠經過解析Request.Url.Query的方式獲取參數 NameValueCollection parames = HttpUtility.ParseQueryString(Request.Url.Query, Encoding.UTF8); string username2 = parames["username"];
若是中文參數值是任意值,沒法判斷是正常值仍是亂碼,可能就要根據不一樣瀏覽器類型,判斷用GB2312解碼仍是utf-8解碼了。固然爲避免沒必要要的麻煩,儘可能url地址中不要含有中文參數(可經過編碼來解決,工行網站就是這麼幹的,url中的中文用了utf-8編碼http://www.icbc.com.cn/ICBC/%e5%ae%a2%e6%88%b7%e6%9c%8d%e5%8a%a1/%e7%83%ad%e7%82%b9%e9%97%ae%e7%ad%94/%e4%b8%aa%e4%ba%ba%e7%94%b5%e5%ad%90%e9%93%b6%e8%a1%8c/default.htm)。函數