Request 接收參數亂碼原理解析三:實例分析


      通過前面兩篇《Request 接收參數亂碼原理解析一:服務器端解碼原理》和《Request 接收參數亂碼原理解析二:瀏覽器端編碼原理》,了解了服務器和瀏覽器編碼解碼的原理,接下來結合項目中遇到的具體問題,分析亂碼問題的解決方法。

      1.用戶身份驗證Cookie亂碼問題

      用戶登錄后,通常用Cookie記錄身份,如把用戶名記錄到Cookie中,其它頁面讀取Cookie,對Cookie值驗證,符合一定規則的話則認為是合法用戶。

        protected void Page_Load(object sender, EventArgs e)
        {
            //假定登陸用戶名為北京(歷史原因系統允許有中文名)
            Response.Cookies["username"].Value = Server.UrlEncode("北京");
        }
登陸成功記錄Cookie
        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頁面

      因為用戶名存在中文問題,寫入編碼和讀取解碼都是在服務器端進行的,所以寫Cookie時將值用Server.UrlEncode()編碼,讀取Cookie值時用Server.UrlDecode()解碼,通常認為這兩個函數是成對出現的,都是由web.config中的globalization結點指定的。

      這段代碼絕大部分運行是沒問題的,但遇到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"))”。

    <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>
Ajax Post請求示例

       2.Url地址欄中的中文參數

       有些頁面地址,由於某些原因帶了中文參數(如http://localhost:52443/Encode/EncodeTest.aspx?username=北京),而這些地址又可能已經被baidu等搜索引擎收錄,因此不能單靠生成新地址規則方式解決,項目必須做到兼容帶中文參數的地址。

       如果是類似示例中的邏輯,中文參數為系統用戶的用戶名,則可以采用先用Request.QueryString方式獲取,得到username如果在系統中存在,則認為得到的參數是正確的;如果username在系統中不存在,則認為可能是因為參數中文亂碼原因引起的,再用NameValueCollection方式獲取一次,解碼方式和系統解碼是不一樣的(系統配置的是GB2312,則指定用utf-8解)。

            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)。


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM