項目經驗分享(中)


   上篇( 項目經驗分享(上))總結了一些瑣碎的小經驗,這篇來講一講在項目中如何解決一個問題,說它是問題,只是針對我個人來講,因為以前沒有處理過類似的問題,主要是分享下我處理這個問題的過程及方法。
   
   項目技術背景:
   1:asp.net mvc 3 項目
   2:登錄機制是采用membership
   3:認證采用Forms驗證
   4:EntityFramwork做為數據訪問
   
   
   問題描述:
   當我們的項目部署到租用的美國服務器上后 (據說是一個雲服務,說的通俗點可能就是在虛似機上的一個IIS站點)出現了用戶需要頻繁登錄的現象,具體來講大約在10分鍾之內就會要求用戶重新登錄。
   
   階段一:
   問題是客戶發現的,他們在UAT時,提到了用戶需要頻繁登錄的問題。
   
   我的反應:
   由於我提供給大家UAT的是一個公共帳號,大家均使用同一帳號登錄,可能會發生不同的人注銷同一帳號的現象,可能存在相互的影響,故建議用戶重新啟用一個全新的帳號。
   
   問題:上面的項目技術背景提到了是采用Forms驗證,而我們是采用默認的Forms驗證機制,即將數據存儲在客戶端,以cookie的形式,故即使多人使用同一帳號,發生不同用戶注銷同一帳戶的現象,也不會影響到其它的用戶的登錄狀態。這也是當時沒太注意的地方,沒找出問題本質的情況下,憑經驗下結論。
   
   階段二:
   客戶再次反應此問題,而且他們明確了自己使用的帳戶是私人的。
   
   我的反應:
   意識到事情的嚴重性,馬上組織測試人員做了仔細的測試,發現問題確實存在,當時就開始着手解決這個問題,畢竟這屬於一個優先級最高的問題。
   
   經過和同事討論以及網上搜索后得到如下方案:
   1:在web.config中設置forms的一個time out
   我們原來的配置如下:
  
<forms loginUrl= " Account/LogOn " defaultUrl= " Account/RaceTemplate ">
   但發現這個值即使不設置,默認時間也有30分鍾,遠大於我們出現問題的10分鍾,但抱着試試看的心情,將之調大到300分鍾,問題依舊。
   
   2:也許和session的設置有關系
   我也忘記當時為什么聯想到session了,也許是我原來的項目都是基於sessio機制的驗證原因吧,但同樣的問題是,session的默認機制也是存儲在進程中,且超時時間為20分鍾,我同樣抱着試試的心情,將這個數值調整到300分鍾,問題依舊。
   

   3:考慮是否和Membersip的設置有關系

   因為我們登錄是采用membership,是否是它有相應的設置,於是開始咨詢同事,結果是,我們的項目是第一個基於membership的項目,網上搜索無果。

   

   問題:這是沒有搞清楚Forms驗證的機制,錯誤的想法,誤認為和mebership本身有關系。

 

   4:懷疑服務器提供商的產品會定期回收我們站點的應用程序池
   這是有依據的,因為我們在自己的本地測試機器上做測試,一點問題都沒有,從不出現頻繁登錄的現象。於時讓相關同事發郵件咨詢服務器提供商,以等待結果。
   
   5:做好服務器提供商無法給出滿意答案的准備。
   如果應用程序池會被定期回收,而服務器提供商無法即時解決被回收的問題時,那么我們嘗試將session存入在數據庫中。畢竟我們不能一直等別人的反饋。
   
   問題:這也是沒有搞清楚Forms驗證的機制,錯誤的想法,誤認為和session有關系,好的是,我們當時只有這個想法 ,並沒有着手去做,因為它有如下問題:
   
   1):這是一種逃避問題的方式。
   即使存儲在進程中有問題,那么我們需要找出其中的原因,而不能因為它有問題就想其它的方法,沒有治本。
   2):session存儲中數據庫中需要部署很多的數據庫腳本。
   這樣一來是工作量增大,二來對現在的系統會有一定影響。
   3):我們租用的數據庫空間很少,只有幾十M,怕影響業務數據的使用。    

 

   從技術手段下手

 

   由於服務器提供商未在短時間內給出正確答案,我開始從技術手段下手,從根本上排查原因。
   此次對Forms驗證做了比較詳細的了解,排除了session和membership的干擾,講的簡單點Forms驗證原理是這樣的:
   
   首先創建一個用戶的票據,經過相應算法的加密,最后將票據保存在cookie中,驗證的過程是首先讀取用戶cookie,如果存在的話,再將票據解密,如果沒有問題即驗證通過。
   
   於時,開始手動編寫登錄邏輯,原來是直接調用授權代碼:
  

FormsAuthentication.SetAuthCookie(model.UserName,  true);

   
   現在開始嘗試以編程方式來授權,即不從配置文件中讀取相關設置,於時有了如下代碼:
  

FormsAuthenticationTicket authTicket =  new FormsAuthenticationTicket( 1, UserName, DateTime.Now, DateTime.Now.AddHours( 20),             

true, UserRole); // User datastring encryptedTicket = FormsAuthentication.Encrypt(authTicket); //加密
            
// 存入Cookie            HttpCookie authCookie = new HttpCookie(FormsAuthentication.FormsCookieName, encryptedTicket);
            authCookie.Expires = authTicket.Expiration;
            Response.Cookies.Add(authCookie);

 

            
    興奮的部署上去之后,仍然是失望而歸。
    
    再次嘗試對讀取cookie做手動編碼:
    

string cookieName = FormsAuthentication.FormsCookieName;
             // get Cookie.
            HttpCookie authCookie = Context.Request.Cookies[cookieName];
             if ( null == authCookie)
                 return;
            FormsAuthenticationTicket authTicket =  null;
          
            authTicket = FormsAuthentication.Decrypt(authCookie.Value);
             if ( null == authTicket)
                 return;

         
             string[] roles = authTicket.UserData.Split( new  char[] {  ' , ' });
            FormsIdentity id =  new FormsIdentity(authTicket);
            GenericPrincipal principal =  new GenericPrincipal(id, roles);
           
            Context.User = principal;

            
     還是失敗則歸。
     
     最后在網上查看到,如果應用程序池被回收,它會重新分配一個machineKey,而這個machineKey會影響到cookie票據,它有兩個重要的屬性:
     validationKey,
     decryptionKey
    它和上面說到的對票據數據的加密,解密,驗證問題有直接關系,這里我就不多講了。如果應用程序池被回收,那么對應的validationKey就會不相同,即與之前的cookie就無法匹配上,這樣就造成了我們需要頻繁登錄。
     
     微軟也非常建議在web項目中配置明確的machineKey,理由如下:
     1:可以解決站點重啟,或者是應用程序池回收造成用戶驗證失敗的現象。
     2:如果是負載均衡的站點,那么他們之間最好也共用同一明確的machineKey。
     
    問題總算找到了,問題也解決了,現在的問題就是應用程序池為什么會被定期回收,這個問題的解釋就不是我們開發組能回答的問題了,我們完成解決了對他們的依賴,即使他們不做解釋不做處理,我們的問題同樣也得到了解決,從而不會影響到用戶體驗以及最終項目上線。    
    

 

總結:
         之所以這樣一個問題困擾我們這么些天(大約一周時間),首要原因是沒有詳細了解Forms驗證的機制,這是我做的第一個Forms驗證項目,所以走了些彎路,容易憑經驗被一些其它信息所干擾。其次是租用服務器問題,我們對於他的定期回收原因,還在排查中,如果不定期回收,此問題也不會出現。所以當出現修改默認值不起作用時,請轉換你的思維方式去嘗試從不同角度分析問題。

 

    參考資料:http://msdn.microsoft.com/en-us/library/ff649308.aspx

 

 


免責聲明!

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



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