最近一直在忙这个小项目,总算忙完了第一版。从今天开始好好完善一下这个系列。
今天要说的就是利用Cookie简单的实现"记住我功能"。用户登录时可以选择"记住我"以此在用户机子上记录Cookie,下次登录系统直接从Cookie中读取用户信息。见下图:
![](https://images.cnblogs.com/cnblogs_com/amar-yao/mvc_login.JPG)
那么代码中怎么实现呢?其实很简单,自定义一个Filter,并集成自AuthorizeAttribute。
![](https://www.cnblogs.com/Images/OutliningIndicators/ContractedBlock.gif)
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方法代码见下:
![](https://www.cnblogs.com/Images/OutliningIndicators/ContractedBlock.gif)
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了。
源代码在已经做了更新,建此系列的首页目录。