麻豆小视频在线观看_中文黄色一级片_久久久成人精品_成片免费观看视频大全_午夜精品久久久久久久99热浪潮_成人一区二区三区四区

首頁(yè) > 學(xué)院 > 開(kāi)發(fā)設(shè)計(jì) > 正文

Request 接收參數(shù)亂碼原理解析一:服務(wù)器端解碼原理

2019-11-17 01:56:05
字體:
來(lái)源:轉(zhuǎn)載
供稿:網(wǎng)友

Request 接收參數(shù)亂碼原理解析一:服務(wù)器端解碼原理

“Server.UrlDecode(Server.UrlEncode("北京")) == “北京””,先用UrlEncode編碼然后用UrlDecode解碼,這條語(yǔ)句永遠(yuǎn)為true嗎?答案是否定的,結(jié)果可能與很多人預(yù)想的不大一樣。本文主要分析這一問(wèn)題出現(xiàn)的原理,研究下Server.UrlEncode(),Server.UrlDecode(),Request["xxx"]三個(gè)函數(shù)與編碼方式的關(guān)系。

1. 問(wèn)題出現(xiàn)的情景

網(wǎng)站采用了GB2312編碼,在Web.config中添加如下配置。

  <system.web>    <globalization requestEncoding="GB2312" responseEncoding="GB2312"/>  </system.web>

測(cè)試頁(yè)面EncodeServerTest.aspx.cs代碼。

        PRotected void Page_Load(object sender, EventArgs e)        {            string s = Server.UrlDecode(Server.UrlEncode("北京"));            bool isEqual = s == "北京";        }

測(cè)試頁(yè)面EncodeServerTest.aspx代碼。

<html xmlns="http://www.w3.org/1999/xhtml"><head runat="server">    <title>頁(yè)面編碼測(cè)試(服務(wù)器端)</title>    <script type="text/javascript" src="Scripts/jquery-2.1.1.min.js"></script></head><body>    <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: "EncodeServerTest.aspx",                data: {name:"name"},                success: function (data) {                    $("#divMessage").html(data);                }            });        }    </script></body></html>
View Code

運(yùn)行頁(yè)面,首次執(zhí)行時(shí),編碼解碼方式都為GB2312,isEuqal=true;點(diǎn)擊頁(yè)面的button,通過(guò)ajax再次請(qǐng)求頁(yè)面,編碼方式仍為GB2312,但解碼方式變成了UTF-8,于是s值成了亂碼,isEqual=false。下面兩個(gè)圖分別為兩次執(zhí)行的結(jié)果:

實(shí)際項(xiàng)目遇到問(wèn)題的場(chǎng)景比這復(fù)雜,但也是因?yàn)閁rlEncode編碼和UrlDecode解碼方式不一致造成的,本系列的第三篇會(huì)有實(shí)際項(xiàng)目場(chǎng)景的說(shuō)明。要解釋這一現(xiàn)象,必須了解UrlEncode()和UrlDecode()的實(shí)現(xiàn)。

2. Server.UrlEncode()函數(shù)

反編譯UrlEncode()函數(shù),實(shí)現(xiàn)如下:

        public string UrlEncode(string s)        {            Encoding e = (this._context != null) ? this._context.Response.ContentEncoding : Encoding.UTF8;            return HttpUtility.UrlEncode(s, e);        }

源碼可以看出,有上下文時(shí)用的是Response.ContentEncoding,沒(méi)有上下文時(shí)默認(rèn)用UTF-8編碼。關(guān)鍵是Response.ContentEncoding的實(shí)現(xiàn),繼續(xù)反編譯ContentEncoding的實(shí)現(xiàn):

        public Encoding ContentEncoding        {            get            {                if (this._encoding == null)                {                    GlobalizationSection globalization = RuntimeConfig.GetLKGConfig(this._context).Globalization;                    if (globalization != null)                    {                        this._encoding = globalization.ResponseEncoding;                    }                    if (this._encoding == null)                    {                        this._encoding = Encoding.Default;                    }                }                return this._encoding;            }        }

結(jié)論:UrlEncode()函數(shù),優(yōu)先從取配置文件的Globalization結(jié)點(diǎn)獲取,如果配置文件沒(méi)有的話用Encoding.Default,最后默認(rèn)用Encoding.UTF8。

3. Server.UrlDecode()函數(shù)

反編譯UrlEncode()函數(shù),實(shí)現(xiàn)如下:

        public string UrlDecode(string s)        {            Encoding e = (this._context != null) ? this._context.Request.ContentEncoding : Encoding.UTF8;            return HttpUtility.UrlDecode(s, e);        }

從源碼可以看出,有上下文時(shí)用的是Request.ContentEncoding,沒(méi)有上下文時(shí)默認(rèn)用UTF-8編碼。關(guān)鍵是Request.ContentEncoding的實(shí)現(xiàn),繼續(xù)反編譯ContentEncoding的實(shí)現(xiàn):

        public Encoding ContentEncoding        {            get            {                if (!this._flags[0x20] || (this._encoding == null))                {                    this._encoding = this.GetEncodingFromHeaders();                    if ((this._encoding is UTF7Encoding) && !AppSettings.AllowUtf7RequestContentEncoding)                    {                        this._encoding = null;                    }                    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);            }        }

從源碼可以看出,Request.ContentEncoding先通過(guò)函數(shù)GetEncodingFromHeaders()獲取,如果獲取不到,則從配置文件獲取,接下來(lái)看GetEncodingFromHeaders()的實(shí)現(xiàn):

        private Encoding GetEncodingFromHeaders()        {            if ((this.UserAgent != null) && CultureInfo.InvariantCulture.CompareInfo.IsPrefix(this.UserAgent, "UP"))            {                string str = this.Headers["x-up-devcap-post-charset"];                if (!string.IsNullOrEmpty(str))                {                    try                    {                        return Encoding.GetEncoding(str);                    }                    catch                    {                    }                }            }            if (!this._wr.HasEntityBody())            {                return null;            }            string contentType = this.ContentType;            if (contentType == null)            {                return null;            }            string attributeFromHeader = GetAttributeFromHeader(contentType, "charset");            if (attributeFromHeader == null)            {                return null;            }            Encoding encoding = null;            try            {                encoding = Encoding.GetEncoding(attributeFromHeader);            }            catch            {            }            return encoding;        }
View Code

從GetEncodingFromHeaders()的源碼可以看出,先從HTTP請(qǐng)求頭(x-up-devcap-post-charset或者charset)獲取編碼信息,如果編碼合法的話則采用HTTP請(qǐng)求頭指定的編碼方式解碼。

結(jié)論:UrlDecode()函數(shù),優(yōu)先從HTTP請(qǐng)求頭(x-up-devcap-post-charset或者charset)獲取編碼,如果沒(méi)指定的話從取配置文件的Globalization結(jié)點(diǎn)獲取,最后默認(rèn)Encoding.UTF8。

通過(guò)對(duì)UrlEncode()和UrlDecode()源碼的分析,可以看出兩者在確定編碼上并不一致,UrlDecode()和HTTP請(qǐng)求的頭有關(guān),而通過(guò)Fiddler對(duì)比EncodeServerTest.aspx頁(yè)面的兩次請(qǐng)求,發(fā)現(xiàn)通過(guò)Ajax方式的請(qǐng)求,請(qǐng)求頭正好多了“Content-Type:application/x-www-form-urlencoded; charset=UTF-8”一句,文章開(kāi)始的問(wèn)題得以解釋。

補(bǔ)充:獲取Response.ContentEncoding和Request.ContentEncoding時(shí),還有一個(gè)重要的函數(shù)”GlobalizationSection globalization = RuntimeConfig.GetLKGConfig(this._context).Globalization“,網(wǎng)上關(guān)于這個(gè)函數(shù)的資料很少,反編譯后代碼也很復(fù)雜,看的云里霧里,下面摘錄一部分代碼,從總可以猜測(cè)這個(gè)函數(shù)的功能:根據(jù)配置文件的繼承關(guān)系,取配置文件中Globalization結(jié)點(diǎn)的Request和Response編碼方式,如果沒(méi)取到的話默認(rèn)取UTF-8編碼,個(gè)人感覺(jué)獲取Request.ContentEncoding時(shí)的分支Encoding.Default賦值應(yīng)該不會(huì)被執(zhí)行。

        internal static RuntimeConfig GetLKGConfig(HttpContext context)        {            RuntimeConfig lKGRuntimeConfig = null;            bool flag = false;            try            {
發(fā)表評(píng)論 共有條評(píng)論
用戶名: 密碼:
驗(yàn)證碼: 匿名發(fā)表
主站蜘蛛池模板: 依依成人精品视频 | 依人在线视频 | 久久99国产精品久久99果冻传媒 | 日韩黄在线观看 | 国产一区二区视频在线播放 | 女教师~淫辱の动漫在线 | 黄色片网站免费在线观看 | 久久手机在线视频 | 久久一区国产 | 亚洲综合精品成人 | 毛片国产 | 欧美一级电影网站 | 国产免费一级淫片a级中文 99国产精品自拍 | 美国黄色小视频 | 久久久tv| 黄网站免费在线看 | 久久久久久久久浪潮精品 | 久久国产精品小视频 | 欧美精品一区二区三区久久久 | 4399一级成人毛片 | 中国女警察一级毛片视频 | 三人弄娇妻高潮3p视频 | 国产精品久久久久久238 | 男女羞羞视频在线免费观看 | 91性视频 | 欧美a区 | 黄色毛片a级 | 美国一级黄色毛片 | 欧美一区在线观看视频 | 日日狠狠久久偷偷四色综合免费 | 亚洲一区成人在线 | 欧美激情在线播放 | 国产一区免费在线 | 成人羞羞视频在线观看免费 | 国产一级片91 | 国内精品国产三级国产a久久 | av电影在线免费 | 欧美成人午夜 | 国产精品高潮视频 | 久久99国产视频 | 色妹子久久 |