在開發中你是否遇到過當使用一個涉及到Cookie操作的網站或者管理系統時,IE 6、7、8、9下都跑的好好的,唯獨到了IE10、11這些高版本瀏覽器就不行了?那麼,我們就來看看,這個問題的前因後果。 先說下之前的2次使用場景: 第一次是在某頁面中,先存Cookie,然後再入庫記錄相關數據,但是發佈到 ...
在開發中你是否遇到過當使用一個涉及到Cookie操作的網站或者管理系統時,IE 6、7、8、9下都跑的好好的,唯獨到了IE10、11這些高版本瀏覽器就不行了?那麼,我們就來看看,這個問題的前因後果。
先說下之前的2次使用場景:
第一次是在某頁面中,先存Cookie,然後再入庫記錄相關數據,但是發佈到生產環境後,入庫操作沒有發生;後來通過列印日誌發現問題卡在這裡:
源碼分享:http://www.jinhusns.com/Products/Download/?type=xcj
if (Request.Browser.Cookies)
也就是說,在客戶端是IE10的環境下,這裡返回False!IE10預設配置下不支持Cookie??
第二次是某地市的升級測試,在IE10的環境下,自服務網站登錄失敗;這個問題很奇怪,因為之前已經升級過多個地市了,IE10使用都正常。這極大的引起了碼農的興趣,由此引出了此文。
描述完場景,我們就來分析分析。雖然直覺告訴碼農,可能是Cookie的讀取或寫入有問題,但畢竟直覺這玩意兒不靠譜,咱還是得用事實和證據說話。國際慣例,先抓個HTTP包瞧瞧:
上圖是IE10下登錄失敗時,服務端返回的HTTP響應頭;下圖是其它瀏覽器正常登錄時,服務端返回的HTTP響應頭,註意紅色框框標註部分;
導致問題的直接原因,很清晰了吧:伺服器響應請求時,沒有回發 Set-Cookie 頭,沒有這個頭,客戶端瀏覽器就無法寫入Cookie。所以基於Form認證(在Cookie中會存入加密票據)的自服務網站,會無法登錄。
這時,你可能會覺得奇怪了,為啥只有IE10、IE11 會這樣,其它IE瀏覽器跑的妥妥的呢?嗯,為了滿足你的好奇心,我們繼續分析。
如果你的機器上裝了.NET的FrameWork,打開這個目錄 C:\Windows\Microsoft.NET\Framework\v4.0.30319\Config\Browsers。科普下,文件夾裡面 的.browser文件是全局訪問的,用於標識發出請求的瀏覽器,並標識這些瀏覽器具備的功能。如果要做定製修改(比如針對特定移動設備),只需把相應 的.browser文件複製到應用程式的\App_Browsers文件夾中修改即可。先用記事本打開 ie.browser 這個文件,
註意圖中標註為紅色部分的正則表達式;然後再來看看,微軟公佈的IE10的User-Agent : Mozilla/5.0 (compatible; MSIE 10.0; Windows NT 6.1; Trident/6.0),MSIE 版本號由以前的1位數字(5-9)變成了現在的2位數字(10),很明顯,無法匹配上面的正則了吧。所以,由於無法正確識別IE10的User- Agent,所以ASP.NET把它看做是未知的瀏覽器,認為它不支持Cookie,由此而產生了一系列與Cookie相關的問題。
問題的根本總算是知道了,那麼該如何解決呢?
其實這個問題已經經過微軟官方確認,是IE10的Bug,其實也可以認為是ASP.NET 2.0、3.5、4.0的Bug,因這些版本都無法識別 IE10的User-Agent。微軟專門發佈了HOTFIX來修複這個問題:
- KB2600088: Hotfix 適用在 Microsoft.NET Framework 4.0 中的 ASP.NET
- KB2608565: Hotfix 適用在 .NET Framework 3.5.1 中的 ASP.NET
- KB2600100: Hotfix 適用在 .NET Framework 3.5 SP1 與 .NET Framework 2.0 SP2 中的 ASP.NET
碼農單位的很多Windows伺服器都會自動更新安裝補丁,所以場景2中說的其它地市使用正常,其實是因為這些伺服器已經打上了補丁,一些新上架、重裝系統的伺服器或自動更新沒有設置的伺服器就很可能會出現這類問題。。。
如果對伺服器沒有操作許可權或者不想打補丁這麼麻煩,比如碼農我,也可以在網站的根目錄,新增一個瀏覽器定義文件,步驟如下:
1、添加一個"App_Browsers"文件夾 ;
2、添加一個"*.browser"尾碼的文件,如 IE10.browser;
3、在文件中添加如下內容(下麵的配置表示,對所有的設備和瀏覽器,都支持Cookies):
<browsers> <browser refID="Default"> <capabilities><!-- To avoid wrong detections of e.g. IE10 --> <capability name="cookies" value="true" /> <capability name="ecmascriptversion" value="3.0" /> </capabilities> </browser> </browsers>
這是針對某個站點的配置,如果既不想打補丁又想對伺服器上的所有站點做全局配置, 要如何處理呢?很容易,其實上面已經明示,問題是出在ie.browser 這個文件的配置上,所以我們只需在原來的基礎上,加上這一串 "\d{2,}$",使ASP.NET 能識別IE10的User-Agent就可以了。修改後的配置如下:
<capability name="majorversion" match="^[6-9]|\d{2,}$" />
修改完後,再到命令行下將修改後的 .browser 文件編譯成程式集並安裝到GAC中,如果是Windows Server 2008、Win7,要以管理員身份運行命令行:C:\Windows\Microsoft.NET\Framework\v4.0.30319 \aspnet_regbrowsers.exe -i
如果是IE11,由於其User-Agent "Mozilla/5.0 (Windows NT 6.3; Trident/7.0; rv:11.0) like Gecko" 變化更大,所以需把下麵這串加入來做匹配:
<!-- Mozilla/5.0 (Windows NT 6.3; Trident/7.0; rv:11.0) like Gecko --> <browser id="IE11Preview" parentID="Mozilla"> <identification> <userAgent match="Trident/(?'layoutVersion'\d+).*rv:(?'revision'(?'major'\d+)(\.(?'minor'\d+)?))" /> <userAgent nonMatch="MSIE" /> </identification> <capabilities> <capability name="browser" value="IE" /> <capability name="layoutEngine" value="Trident" /> <capability name="layoutEngineVersion" value="${layoutVersion}" /> <capability name="isColor" value="true" /> <capability name="screenBitDepth" value="8" /> <capability name="ecmascriptversion" value="3.0" /> <capability name="jscriptversion" value="6.0" /> <capability name="javascript" value="true" /> <capability name="javascriptversion" value="1.5" /> <capability name="w3cdomversion" value="1.0" /> <capability name="ExchangeOmaSupported" value="true" /> <capability name="activexcontrols" value="true" /> <capability name="backgroundsounds" value="true" /> <capability name="cookies" value="true" /> <capability name="frames" value="true" /> <capability name="javaapplets" value="true" /> <capability name="supportsCallback" value="true" /> <capability name="supportsFileUpload" value="true" /> <capability name="supportsMultilineTextBoxDisplay" value="true" /> <capability name="supportsMaintainScrollPositionOnPostback" value="true" /> <capability name="supportsVCard" value="true" /> <capability name="supportsXmlHttp" value="true" /> <capability name="tables" value="true" /> <capability name="supportsAccessKeyAttribute" value="true" /> <capability name="tagwriter" value="System.Web.UI.HtmlTextWriter" /> <capability name="vbscript" value="true" /> <capability name="revmajor" value="${major}" /> <capability name="revminor" value="${minor}" /> </capabilities> </browser>原文來自於《博客園》 免費培訓課:http://www.jinhusns.com/Products/Curriculum/?type=xcj