Asp.Net 4.0 FormAuthentication 原理


 

建立一個使用Asp.Net Membership管理登陸登出信息的網站

 

1. 創建一個Asp.Net Mvc 3 示例網站。

image

2. 創建自定義的MemberShipProvider,並在Web.CONFIG中配置生效。

a. 創建MyMmbProv

   1: public class MyMmbProv : MembershipProvider
   2: {
   3:  
   4: ...........
   5:     ///implement ValidateUser just return true, so any user name will be ok
   6:     public override bool ValidateUser(string username, string password)
   7:     {
   8:         return true;
   9:     }
  10: }

b. 配置Web.config的Membership/Providers節點。

   1: <;membership defaultProvider="MySqlMembershipProvider">
   2:   <;providers>
   3:     <;clear/>
   4:     <;add name="MySqlMembershipProvider" type="CookieTest.Provider.MyMmbProv" connectionStringName="ApplicationServices"
   5:          enablePasswordRetrieval="false" enablePasswordReset="true" requiresQuestionAndAnswer="false" requiresUniqueEmail="false"
   6:          maxInvalidPasswordAttempts="5" minRequiredPasswordLength="6" minRequiredNonalphanumericCharacters="0" passwordAttemptWindow="10"
   7:          applicationName="/" />;    
   8:   </providers>

         注意membership節點的defaultProvider 要設置為新增的MembershipProvider節點的名稱。

3. 設置網站認證模式為Form

   1: <;authentication mode="Forms">
   2:   <;forms loginUrl="~/Account/LogOn" timeout="20" name="cookie_test" defaultUrl="~/Home/About" slidingExpiration="false"  cookieless="UseUri"/>
   3: </authentication>

此時Form認證使用Uri來存儲cookie信息。

 

測試UseUri Form認證

登陸后發現頁面的url中多了一長串類似加密cookie的內容:http://192.168.4.22/(F(fyt-FBDHvrANVba89TNUrMqn9w_ZgSN9xNEX3C8yIfbRIA-q6IyZhnKFh9mWwLN2kxuFUs0HxlKSTBSp7wPyoqxQhJGsguu1lbwjERZ3kfiHt1w7oD8x9LcGwZNjlY-yzM81YcMVyxbY3G74Yp5YOhGswI5NIg4Ehq3FOu0WbSo5BEkUeDbVFkeflmXZDfD70))/Home/About 而且LogOnPartial中顯示出剛才登陸時輸入的用戶名稱

image

將上述url粘貼到別的瀏覽器(或者其他同一局域網的機器上)(如上次測試使用chrome,這次使用firefox),發現自動登陸進去了,而且顯示出同樣的用戶名,說明在該URL中至少已經包含了用戶名稱信息。

 

也就是說只要能夠拿到用戶登陸的URL就可以直接登陸該用戶的賬號!

 

測試UseCookies Form認證

將cookieless屬性改為UseCookies

   1: <;authentication mode="Forms">
   2:   <;forms loginUrl="~/Account/LogOn" timeout="20" name="cookie_test" defaultUrl="~/Home/About" slidingExpiration="false"  cookieless="UseCookies"/>
   3: </authentication>

用戶登陸后每次頁面請求都會帶上cookie:

image

從上圖中看到登陸數據提交后,返回的Response Headers有一個Set-Cookie的屬性,這就是該用戶的cookie信息。

登陸后查看其他頁面時的頁面數據如下圖:

image

 

可以看到,登陸后每個頁面請求的Request Headers 都會加上Cookie(如上圖)。

那如果我們通過javascript給未登陸頁面增加上述cookie信息結果會是怎樣呢?

   1: <script type="text/javascript">
   1:  
   
   
   
           
   2:     $(document).ready(function () {
   
   
   
           
   3:         $("#setCookie").click(function () {
   
   
   
           
   4:             var cookieVal = $("#inputCookie").val();
   
   
   
           
   5:             document.cookie = cookieVal;
   
   
   
           
   6:         });
   
   
   
           
   7:     });
   
   
   
           
   8:  
   
   
   
           </script>
   2: <h2>About</h2>
   3: <p>
   4:     Put content here.
   5:     <br/>
   6:     SessionId: @Session.SessionID
   7:     
   8: </p>
   9: <div>
  10:     <input type="text" id="inputCookie" />
  11:  
  12:     <br/>
  13:  
  14:     <input id="setCookie" value="Set Cookie" type="button"/>
  15: </div>

 

 

此時頁面上顯示為已登錄狀態,不過繼續訪問其他的頁面會有所不同:其中無需認證的頁面不會顯示登錄用戶信息;而有認證要求的頁面卻會顯示出登錄用戶的信息。

 

再將cookie_test=XXXXXXXXX賦給該頁面,然后刷新頁面發現已經是登出狀態。

 

由此可見整個Asp.Net 的FormAuthentication都是依賴於cookie或者uri來實現登錄的。

 

在類FormsAuthentication中可以看到:

   1: private static HttpCookie GetAuthCookie(string userName, bool createPersistentCookie, string strCookiePath, bool hexEncodedTicket)
   2: {
   3:   FormsAuthentication.Initialize();
   4:   if (userName == null)
   5:     userName = string.Empty;
   6:   if (strCookiePath == null || strCookiePath.Length < 1)
   7:     strCookiePath = FormsAuthentication.FormsCookiePath;
   8:   DateTime utcNow = DateTime.UtcNow;
   9:   DateTime expirationUtc = utcNow.AddMinutes((double) FormsAuthentication._Timeout);
  10:   FormsAuthenticationTicket ticket = FormsAuthenticationTicket.FromUtc(2, userName, utcNow, expirationUtc, createPersistentCookie, string.Empty, strCookiePath);
  11:   string str = FormsAuthentication.Encrypt(ticket, hexEncodedTicket);
  12:   if (str == null || str.Length < 1)
  13:     throw new HttpException(System.Web.SR.GetString("Unable_to_encrypt_cookie_ticket"));
  14:   HttpCookie httpCookie = new HttpCookie(FormsAuthentication.FormsCookieName, str);
  15:   httpCookie.HttpOnly = true;
  16:   httpCookie.Path = strCookiePath;
  17:   httpCookie.Secure = FormsAuthentication._RequireSSL;
  18:   if (FormsAuthentication._CookieDomain != null)
  19:     httpCookie.Domain = FormsAuthentication._CookieDomain;
  20:   if (ticket.IsPersistent)
  21:     httpCookie.Expires = ticket.Expiration;
  22:   return httpCookie;
  23: }

FromsAuthenticationTicket 包含了用戶信息、過期時間、是否持久化、cookie路徑,並且進過了加密處理。

 

另外:登陸時勾選記住密碼后在..\Windows\Temporary Internet Files\ 文件夾中會多出一個文件

image

文件的內容如下:

cookie_test
39F80DBA2E9193EF18498E9B65186DAA0A259873DA0EF839990D457F53BBE2270325838A1BF9FF7409E10E8B13C1E7C805B3F2621C22065EEFAB12F953E4523163FD4ACC9F5312F0EC66112A81FDFFF2B5564481526D5B996F13EA42219AE760DD68CEEDD7E40E8BCD3F68D6E1BC0D73EE9D13798BAFB38B6143B334BE70BD31995430B3FCF90DC3A0514DB180682B9E
192.168.1.3/
9728
3254446592
30352998
4140518480
30352995
*

 

與Request Header 中的Cookie內容比較

cookie_test=39F80DBA2E9193EF18498E9B65186DAA0A259873DA0EF839990D457F53BBE2270325838A1BF9FF7409E10E8B13C1E7C805B3F2621C22065EEFAB12F953E4523163FD4ACC9F5312F0EC66112A81FDFFF2B5564481526D5B996F13EA42219AE760DD68CEEDD7E40E8BCD3F68D6E1BC0D73EE9D13798BAFB38B6143B334BE70BD31995430B3FCF90DC3A0514DB180682B9E

 

多出了IP地址以及過期時間。

cookie的寫入讀取都是由CookielessHelperClass來完成的。

本文測試代碼

 


免責聲明!

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



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