• 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路径,并且进过了加密处理。

    另外:登陆时勾选记住密码后在..WindowsTemporary Internet Files 文件夹中会多出一个文件

    image

    文件的内容如下:

    cookie_test
    39F80DBA2E9193EF18498E9B65186DAA0A259873DA0EF839990D457F53BBE2270325838A1BF9FF7409E10E8B13C1E7C805B3F2621C22065EEFAB12F953E4523163FD4ACC9F5312F0EC66112A81FDFFF2B5564481526D5B996F13EA42219AE760DD68CEEDD7E40E8BCD3F68D6E1BC0D73EE9D13798BAFB38B6143B334BE70BD31995430B3FCF90DC3A0514DB180682B9E
    192.168.1.3/
    9728
    3254446592
    30352998
    4140518480
    30352995
    *

    与Request Header 中的Cookie内容比较

    cookie_test=39F80DBA2E9193EF18498E9B65186DAA0A259873DA0EF839990D457F53BBE2270325838A1BF9FF7409E10E8B13C1E7C805B3F2621C22065EEFAB12F953E4523163FD4ACC9F5312F0EC66112A81FDFFF2B5564481526D5B996F13EA42219AE760DD68CEEDD7E40E8BCD3F68D6E1BC0D73EE9D13798BAFB38B6143B334BE70BD31995430B3FCF90DC3A0514DB180682B9E

    多出了IP地址以及过期时间。

    cookie的写入读取都是由CookielessHelperClass来完成的。

    本文测试代码

  • 相关阅读:
    C# Large Files MD5 C# 获取大文件MD5
    C# SmtpClient 发邮件
    Windows Server 2008 R2 install Visual Studio 2015 failed
    C# 下载泛型数据
    SetApartmentState(ApartmentState state).Ensure that your Main function has STAThreadAttribute marked on it. This exception is only raised if a debugger is attached to the process
    ADO.NET
    WPF DataGrid row background converter datagrid 行背景随绑定数据变化,转换器
    C# 截图ScreenCapture,保存
    打印发现function toUpperCase() { [native code] }
    正则匹配test
  • 原文地址:https://www.cnblogs.com/philzhou/p/AspNet_FormAuthentication.html
Copyright © 2020-2023  润新知