寫這個以前特地找了下,看到也有這方面的別人寫的文章資料,可是貌似都是相似於這個的:html
http://www.cnblogs.com/New-world/p/3865939.htmlredis
想了下,要不要把本身作的寫出來。這裏記錄下吧。chrome
基本場景描述:用戶ericlee先打開一個瀏覽器如chrome,輸入帳號密碼,在某系統登陸成功了,他再打開一個瀏覽器如firefox,再輸入同一個帳號密碼,仍是登陸成功了(固然,一樣的帳號密碼嘛)。他再來操做以前的chrome瀏覽器,發現登陸效果還在,沒被踢下線,系統仍是能夠操做。他可能就不開心了,也許他但願這個時候他以前在chrome瀏覽器的登陸被擠下線的。json
用戶是衣食父母,爲了讓衣食父母開心,咱們來知足一下他們這個小小的願望。瀏覽器
基本思路: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不是最新登陸的狀態,讓他回登陸頁面吧,走好不送。緩存
來一個代碼嚐嚐:服務器
一、自定義的CurrentUsercookie
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; } } }
二、用戶登陸與註銷代碼:(稍微說下,這裏用到了自定義的CurrentUser類,使用到了Json序列化,DES加密與解密,Cookie操做等等等)mvc
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 }
三、說好的過濾器必定要:dom
[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!!