IE10、IE11 User-Agent 導致的 ASP.Net 網站無法寫入Cookie 問題


  

  你是否遇到過當使用一個涉及到Cookie操作的網站或者管理系統時,IE 6、7、8、9下都跑的好好的,唯獨到了IE10、11這些高版本瀏覽器就不行了?好吧,這個問題碼農連續2天內遇到了2次。那么,我們就來看看,這個問題的前因后果。

  先說下這2次的使用場景,一次是在某頁面中,先存Cookie,然后再入庫記錄相關數據,但是發布到生產環境后,入庫操作沒有發生;后來通過打印日志發現問題卡在這里:

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來修復這個問題:

      碼農單位的很多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>

   三板斧搞定!

  幸福來的就是這么突然~~~ 

 


免責聲明!

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



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