寫這個之前特意找了下,看到也有這方面的別人寫的文章資料,但是貌似都是類似於這個的:
http://www.cnblogs.com/New-world/p/3865939.html
想了下,要不要把自己做的寫出來。這里記錄下吧。
基本場景描述:用戶ericlee先打開一個瀏覽器如chrome,輸入賬號密碼,在某系統登錄成功了,他再打開一個瀏覽器如firefox,再輸入同一個賬號密碼,還是登錄成功了(當然,同樣的賬號密碼嘛)。他再來操作之前的chrome瀏覽器,發現登錄效果還在,沒被踢下線,系統還是可以操作。他可能就不開心了,也許他希望這個時候他之前在chrome瀏覽器的登錄被擠下線的。
用戶是衣食父母,為了讓衣食父母開心,我們來滿足一下他們這個小小的願望。
基本思路:ericlee在chrome瀏覽器登錄的時候將他的登錄名(ericlee)與當前時間Datetime.Now收集起來放到一個對象里(CurrentUser的一個實例cuser),再把cuser做成json,保存到瀏覽器cookie中,再保存到緩存中(我用的是redis)。當ericlee在操作系統的時候,會經過一個Controller吧?Controller可以定義過濾器的吧?對的,就使用過濾器。每次操作,都在過濾器里從cookie里獲取cuser,再從緩存中獲取cuser,它兩個都是字符串,看它們兩個是否一樣咯。完全一樣的話,是可以保證登錄時間一樣的,登錄時間一樣的話,就可以說明這兩個東東是同一次登錄造成的結果。當ericlee再在firefox中登錄的時候,沒問題,這里我沒打算說當有人已在登錄狀態的時候不允許再次登錄同一個賬號,So,很順利的,ericlee在firefox中登錄還是成功的(當然前提是輸入正確的賬號密碼)。這樣,當ericlee再回到chrome中再來操作系統的時候,過濾器就起作用了,從chrome的cookie中獲取到的他的登錄時間比如是2016/03/12 22:16:23.336,然而從緩存中獲取到的登錄時間是2016/03/12 22:20:55.256,這樣,方便的判斷出chrome不是最新登錄的狀態,讓他回登錄頁面吧,走好不送。
來一個代碼嘗嘗:
1、自定義的CurrentUser
public class CurrentUser { public string UserID { get; set; } public string LoginName { get; set; } public DateTime? LastLoginTime { get; set; } public static CurrentUser GetCurrentUser() { if (HttpContext.Current == null) { return null; } CurrentUser cuser = null; string cookieLoginInfo = CookieMgr.Get(UserBLL.LoginCookieName); if (!string.IsNullOrEmpty(cookieLoginInfo)) { var CrypteKey = ConfigMgr.GetAppSettingString("CrypteKey"); cuser = JsonConvert.DeserializeObject<CurrentUser>(Cryptor.DesDecrypt(cookieLoginInfo, CrypteKey)); string cacheLoginInfo = CacheMaker.Cache.Get<string>(cuser.UserID); if (!string.IsNullOrEmpty(cacheLoginInfo)) { if(cookieLoginInfo.Equals(cacheLoginInfo)) { return cuser; } else { return null; } } else { return null; } } else { return null; } } }
2、用戶登錄與注銷代碼:(稍微說下,這里用到了自定義的CurrentUser類,使用到了Json序列化,DES加密與解密,Cookie操作等等等)
public class UserBLL { public static string LoginCookieName=ConfigMgr.GetAppSettingString("LoginCookieName"); #region 登錄注銷 /// <summary> /// 登錄,將用戶信息保存到瀏覽器的cookie與服務器cache里 /// </summary> /// <param name="Model"></param> /// <returns></returns> public static bool SignIn(SysUser Model) { CurrentUser cuser = new CurrentUser(); cuser.UserID = Model.ID; cuser.LoginName = Model.LoginName; cuser.LastLoginTime = DateTime.Now; var cuserStr = Newtonsoft.Json.JsonConvert.SerializeObject(cuser); var CrypteKey = ConfigMgr.GetAppSettingString("CrypteKey"); var cuserHash = Cryptor.DesEncrypt(cuserStr, CrypteKey); string domain = CookieMgr.GetDomain(HttpContext.Current.Request.Url.ToString()); CookieMgr.Set(LoginCookieName, cuserHash, 0, domain); if (CacheMaker.Cache.Set(cuser.UserID, cuserHash)) { return true; } else { CookieMgr.Remove(LoginCookieName); return false; } } /// <summary> /// 注銷,清除瀏覽器的cookie和服務器中緩存的用戶信息 /// </summary> /// <returns></returns> public static bool SignOut() { var cuser=CurrentUser.GetCurrentUser(); if (cuser == null) { return false; } else { CookieMgr.Remove(LoginCookieName); CacheMaker.Cache.Remove(cuser.UserID); return true; } } #endregion }
3、說好的過濾器一定要:
[AttributeUsage(AttributeTargets.Class | AttributeTargets.Method, AllowMultiple = false, Inherited = false)] public class LSAuthorizeAttribute : FilterAttribute, IAuthorizationFilter { public LSAuthorizeAttribute() { }
public virtual void OnAuthorization(AuthorizationContext filterContext) { if (filterContext == null) { throw new ArgumentNullException("filterContext"); } CurrentUser cuser; UrlHelper Url = new UrlHelper(filterContext.RequestContext); var request = filterContext.RequestContext.HttpContext.Request; string url = string.Empty; if (IsSignIn(request, out cuser)) { ControllerBase c = filterContext.Controller; PropertyInfo p = c.GetType().GetProperty("cuser"); p.SetValue(c, cuser); } else { url =string.IsNullOrEmpty(url)? Url.Action("login", "index",new { area = "", returnurl = request["returnurl"] }):url; //HttpContext.Current.Response.Redirect(url, true); //return; filterContext.Result = new RedirectResult(url); } } /// <summary> /// 判斷當前請求是否還了用戶登錄的cookie信息,如果帶了,則再判斷服務器緩存中記錄是否有該用戶的登錄信息並是否一致 /// </summary> /// <param name="request"></param> /// <param name="cuser"></param> /// <returns></returns> private bool IsSignIn(HttpRequestBase request,out CurrentUser cuser) { cuser = null; string cookieLoginInfo=CookieMgr.Get(UserBLL.LoginCookieName); if (!string.IsNullOrEmpty(cookieLoginInfo)) { var CrypteKey = ConfigMgr.GetAppSettingString("CrypteKey"); cuser = JsonConvert.DeserializeObject<CurrentUser>(Cryptor.DesDecrypt(cookieLoginInfo, CrypteKey)); string cacheLoginInfo = CacheMaker.Cache.Get<string>(cuser.UserID); if (!string.IsNullOrEmpty(cacheLoginInfo)) { return cookieLoginInfo.Equals(cacheLoginInfo); } else { return false; } } else { return false; } } }
關於過濾器,要了解簡單的可以看這個:
http://www.cnblogs.com/ben-zhang/archive/2013/03/11/2954298.html
想看詳細的,可以看這個:
http://www.fwqtg.net/asp-net-mvc-%E8%BF%87%E6%BB%A4%E5%99%A8%E8%AF%A6%E8%A7%A3.html
詳細這個太多我表示沒有看完。
大概的就這樣子,醬,night!!