建立一個使用Asp.Net Membership管理登陸登出信息的網站
1. 創建一個Asp.Net Mvc 3 示例網站。
2. 創建自定義的MemberShipProvider,並在Web.CONFIG中配置生效。
a. 創建MyMmbProv
1: public class MyMmbProv : MembershipProvider2: {
3:
4: ...........
5: ///implement ValidateUser just return true, so any user name will be ok6: 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中顯示出剛才登陸時輸入的用戶名稱
將上述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:
從上圖中看到登陸數據提交后,返回的Response Headers有一個Set-Cookie的屬性,這就是該用戶的cookie信息。
登陸后查看其他頁面時的頁面數據如下圖:
可以看到,登陸后每個頁面請求的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\ 文件夾中會多出一個文件
文件的內容如下:
cookie_test
39F80DBA2E9193EF18498E9B65186DAA0A259873DA0EF839990D457F53BBE2270325838A1BF9FF7409E10E8B13C1E7C805B3F2621C22065EEFAB12F953E4523163FD4ACC9F5312F0EC66112A81FDFFF2B5564481526D5B996F13EA42219AE760DD68CEEDD7E40E8BCD3F68D6E1BC0D73EE9D13798BAFB38B6143B334BE70BD31995430B3FCF90DC3A0514DB180682B9E
192.168.1.3/
9728
3254446592
30352998
4140518480
30352995
*
與Request Header 中的Cookie內容比較
cookie_test=39F80DBA2E9193EF18498E9B65186DAA0A259873DA0EF839990D457F53BBE2270325838A1BF9FF7409E10E8B13C1E7C805B3F2621C22065EEFAB12F953E4523163FD4ACC9F5312F0EC66112A81FDFFF2B5564481526D5B996F13EA42219AE760DD68CEEDD7E40E8BCD3F68D6E1BC0D73EE9D13798BAFB38B6143B334BE70BD31995430B3FCF90DC3A0514DB180682B9E
多出了IP地址以及過期時間。
cookie的寫入讀取都是由CookielessHelperClass來完成的。
本文測試代碼