最近一直在忙这个小项目,总算忙完了第一版。从今天开始好好完善一下这个系列。
  今天要说的就是利用Cookie简单的实现"记住我功能"。用户登录时可以选择"记住我"以此在用户机子上记录Cookie,下次登录系统直接从Cookie中读取用户信息。见下图:  

   那么代码中怎么实现呢?其实很简单,自定义一个Filter,并集成自AuthorizeAttribute。   

 Code
Code
 1 [SuppressMessage("Microsoft.Performance", "CA1813:AvoidUnsealedAttributes",
 2     Justification = "Unsealed so that subclassed types can set properties in the default constructor or override our behavior.")]
 3     [AttributeUsage(AttributeTargets.Class | AttributeTargets.Method, Inherited = true, AllowMultiple = true)]
 4     public class CookieAuthorizeAttribute : AuthorizeAttribute
 5     {
 6         private string[] _rolesSplit = new string[0];
 7         private string[] _usersSplit = new string[0];
 8 
 9         protected override bool AuthorizeCore(HttpContextBase httpContext)
10         {
11             if (httpContext == null)
12             {
13                 throw new ArgumentNullException("httpContext");
14             }
15 
16             IPrincipal user = httpContext.User;
17             if (!user.Identity.IsAuthenticated)
18             {
19                 //从Cookie中取 
20                 if (httpContext.Request.Cookies.Get(SessionKey.Cookie_UserName) != null)
21                 {
22                     string cookie = httpContext.Request.Cookies[SessionKey.Cookie_UserName].Value;
23                     if (!String.IsNullOrEmpty(cookie))
24                     {
25                         FormsAuthentication.SetAuthCookie(cookie, false);
26                         //初始化Session,典型的XP风格,这里耦合度很大
27                         ControllerExt.InitSession(cookie, httpContext);
28                         return true;
29                     }
30                 }
31                 return false;
32             }
33 
34             if (_usersSplit.Length > 0 && !_usersSplit.Contains(user.Identity.Name, StringComparer.OrdinalIgnoreCase))
35             {
36                 return false;
37             }
38 
39             if (_rolesSplit.Length > 0 && !_rolesSplit.Any(user.IsInRole))
40             {
41                 return false;
42             }
43 
44             return true;
45         }
46     }  其实最核心的就是20-29行。如果用户没有通过验证,我们就从Cookie中取用户信息(Cookie中存放的是UserId)。如果没有取到就返回false表示登录失败。如果取到了就通过ControlExt的Initsession方法将完整的用户实体(这里是User类实例)放到Session中。供程序其他部分使用。
  Initsession方法代码见下:  

 Code
Code
 1 /// <summary>
 2         /// 初始化Session中的User信息
 3         /// </summary>
 4         public static void InitSession(string userId,HttpContextBase httpContext)
 5         {
 6             try
 7             {
 8                 IUserRepository service = new UserRepository();
 9                 List<User> users = service.FindUsers(new Where[] 
10                         { 
11                             new Where()
12                             {
13                                 ColumnName = FieldConst.Field_Users_UserId,
14                                 Comparison = Comparison.Equals,
15                                 Condition = Where.WhereCondition.AND,
16                                 DbType = System.Data.DbType.String,
17                                 ParameterValue = userId,
18                                 TableName = TableConst.Table_Users
19                             }
20                         });
21                 if (users != null && users.Count > 0)
22                     httpContext.Session[SessionKey.Session_User] = users[0];
23             }
24             catch (Exception ex)
25             {
26                 Log.Error("初始化用户Session出错.", ex);
27             }
28         }  其中涉及的SmartDAL访问数据库的部分代码我们后面章节再详细讨论。
  等等,这里注重架构的朋友又要说了,在这里访问数据库不太合适,使代码的耦合度变大。由于时间比较紧,而且这又只是一个小东西所以我没有太多的关注这些。只是随自己想怎么写就怎么写(典型的XP思想是么?呵呵)。欢迎对此有异议的朋友与我讨论。
  这样把CookieAuthorizeAttribute应用到需要登录验证的Controller或是Action就OK了。
  源代码在已经做了更新,建此系列的首页目录。