架構:前端
基本實現都差很少,有以下幾大模塊吧:① 都是會有一個 Auth類 或者 Identity類 專門負責處理 登錄、退出、是否登錄、以及Cookie記錄等操做。② 在進入每一個基本頁面(WebForm)或者控制器(MVC-Controller)前會先進入一個處理的方法中,這個方法根據架構不一樣實現的方式不一樣。③ 登錄頁或登錄控制器,這裏的做用傻子都知道,就是在用戶登錄或者進入其餘帶有權限的地方被攔截後跳轉到這裏處理的。面試
⑴ WebForm 中實現:瀏覽器
① 這裏統一交 Identility 類 吧,這裏主要三個方法【登錄、退出、是否登錄】以及一些基本字段(字段供後面使用,如記錄日誌之類的),登錄方法負責校驗帳號及密碼,這裏的密碼校驗通常是先將密碼按照原有的規則採用MD5加密,完後再和庫中的用戶密碼作比較(這是一個md5碰撞的過程),失敗則在登錄頁面拋錯,成功的話要記錄會經過FormAuthentication.SetAuthCookie()方法記錄Cookie,這裏會有人問爲何要經過那個方法來設置Cookie呢?固然你說你任性,能夠不用,那你本身來經過解析Cookie來設置IsAuthenticated 從而判斷用戶是否登錄,這裏是爲了使用.NET自帶的身份認證,使用上述方法後,你能夠經過HttpContext.Current.User.Identity.IsAuthenticated來驗證用戶是否登錄了,由於它返回一個bool值。退出方法就是清掉Cookie,跳轉到登錄頁面便可,很簡單;判斷用戶是否登錄方法,直接調取剛剛說的HttpContext.Current.User.Identity.IsAuthenticated 或者 調取你本身任性寫的 IsAuthenticated 屬性也行。cookie
② WebForm實現這一步是經過繼承一個基類頁面 假設爲 PageBase 類,基類 PageBase 又繼承 System.Web.UI.Page,在這個基類裏要重寫 Page 類 的OnInit() 方法,這個方法是在進入頁面前先進入這個方法,在這裏你能夠判斷用戶是否登錄,未登陸則直接 Response.Write("登錄頁.aspx");這裏注意一點,面試時候有些傻逼面試官會問你子頁面的OnInit()方法以及Onload()方法和基類頁面的OnInit()和Onload()方法的執行順序,不要被面試官的淫威所嚇倒,這裏就是一個遞歸嵌套執行的過程,先執行子頁面的OnInit()方法,這裏會調用基類的OnInit(),基類的執行完後,在回到子頁面的OnInit()的方法,完後執行完畢,Onload()同理。架構
③ 這一步最簡單了,登錄的調用 Identity 類的登錄方法,退出調用退出方法便可。最多在前端加些請求操做(表單提交或者Ajax異步,看本身喜愛)。框架
⑵ Mvc中實現:異步
① 第一步這裏和Webform實現基本同樣,不說了。ide
② 第二步,既然用的MVC框架,那麼就要Filter過濾器來實現了,這裏咱們能夠建一個文件夾命名爲Filter,建立一個類,記得類名要以 Attribute 結尾,例如就叫 IdentityAithorizeAttribute,該類須要繼承ActionFilterAttribute屬性,類內經過重寫OnActionExecuting()方法內調用Identity的IsAuthenticated ,判斷是否登錄,未登陸的話跳轉到登錄頁。完後在須要限制的控制器或者操做上添加[IdentityAuthorize]特性來實現限制攔截。加密
③ 同WebFrom的③,Mvc通常會採用Ajax異步的方式提交來提升用戶的體驗性。url
總結:
這只是根據本身現有的技術認知總結出來的,因此可能會存在必定的侷限性。寫這篇文章以前,以爲可能會有不少內容涉及進來,邊寫邊發現其實好多技術都是相通的,只是實現方式不一樣罷了,因此越日後寫越簡略了,固然這和如今的咱們對MVC更瞭解,因此隨便寫寫你們也能看懂,哈哈哈。有一點注意,在插入Cookie的時候必定要設置爲只讀,否則會有Cookie被串改的風險。腳本是能夠操做Cookie的,這一點你們是知道的。
即: System.Web.HttpContext.Current.Response.Cookies[key].HttpOnly = true;
登陸方法類:
public class Identity { /// <summary> /// UserID /// </summary> private string id = string.Empty; public string ID { get { return id; } set { id = value; } } /// <summary> /// 用戶名 /// </summary> public string UserName { get; set; } public static Identity User { get { try { Identity user = new Identity(); var key = string.Format("{0}.Identity", BuShare.Config.CookiePrefix); var cookies = HttpContext.Current.Request.Cookies; if (cookies != null && cookies.AllKeys.Contains(key)) { var value = cookies[key].Value; if (string.IsNullOrEmpty(value)) { return null; } else { string[] userValue = value.Split('^'); user.ID = userValue[0]; user.UserName = userValue[1]; return user; } } else { return null; } } catch (Exception) { return null; } } } /// <summary> /// 注入登陸Cookies /// </summary> /// <param name="user"></param> public static void Login(En.User user) { var cookies = HttpContext.Current.Response.Cookies; var key = string.Format("{0}.Identity", BuShare.Config.CookiePrefix); cookies[key].Value = CreateCookiesValue(user.ID, user.UserName); cookies[key].HttpOnly = true;//關閉瀏覽器cookie失效 cookies[key].Domain = BuShare.Config.CookieDomain; var cookiesDelay = HttpContext.Current.Response.Cookies; var keyDelay = string.Format("{0}.Delay", BuShare.Config.CookiePrefix); cookiesDelay[keyDelay].Value = CreateCookiesValue(DateTime.Now.ToString(), "Delay"); cookiesDelay[keyDelay].Expires = DateTime.Now.AddMinutes(30); cookiesDelay[keyDelay].Domain = BuShare.Config.CookieDomain; } /// <summary> /// 生成登陸Cookies的Value方法 /// </summary> /// <param name="userID"></param> /// <param name="username"></param> /// <returns></returns> private static string CreateCookiesValue(string userID, string username) { try { if (string.IsNullOrWhiteSpace(userID) || string.IsNullOrWhiteSpace(username)) { return ""; } //string clientIP = HttpContext.Current.Request.UserHostAddress; //string userAgent = HttpContext.Current.Request.UserAgent; string value = ""; //TODO:自定義方法生成value;(驗證cookie的時候經過該方法對應程序驗證) //value經過指定的密鑰DES加密 value = Bu.Des.Encrypt(value, Config.SecurityKey); return userID + "^" + HttpUtility.UrlEncode(username) + "^" + value; } catch (Exception) { throw; } } public static bool IsHavingLogin() { try { var key = string.Format("{0}.Identity", Config.CookiePrefix); var cookies = HttpContext.Current.Request.Cookies; #region 延時Cookies var keyDelay = string.Format("{0}.Delay", Config.CookiePrefix); var cookiesDelay = HttpContext.Current.Request.Cookies; if (cookiesDelay != null && cookies != null && cookiesDelay.AllKeys.Contains(keyDelay) && cookies.AllKeys.Contains(key)) { HttpContext.Current.Response.Cookies.Remove(keyDelay); cookiesDelay[keyDelay].Value = CreateCookiesValue(DateTime.Now.ToString(), "Delay"); cookiesDelay[keyDelay].Expires = DateTime.Now.AddMinutes(30); cookiesDelay[keyDelay].Domain = Config.CookieDomain; return true; } else { return false; } #endregion #region 主Cookies if (cookies != null && cookies.AllKeys.Contains(key)) { var value = cookies[key].Value; if (string.IsNullOrEmpty(value)) { return false; } else { string ip = HttpContext.Current.Request.UserHostAddress; return IsValidCookies(value); } } #endregion } catch (Exception) { throw; } } private static bool IsValidCookies(string cookie) { try { if (string.IsNullOrEmpty(cookie)) { return false; } string[] CookiesValues = cookie.Split('^'); if (CookiesValues == null) { return false; } //TODO:自定義方法驗證Cookie值(和生成Cookie值得方法對應) //若是cookie值有效 if (TODO:CookiesValues == true) { return true; } } catch (Exception) { throw; } return false; } public static void Logout() { var cookies = HttpContext.Current.Response.Cookies; var key = string.Format("{0}.Identity", Config.CookiePrefix); cookies[key].Value = null; cookies[key].HttpOnly = true;//關閉瀏覽器cookie失效 cookies[key].Domain = Config.CookieDomain; var cookiesDelay = HttpContext.Current.Response.Cookies; var keyDelay = string.Format("{0}.Delay", Config.CookiePrefix); cookiesDelay[keyDelay].Value = null; cookiesDelay[keyDelay].Expires = DateTime.Now.AddDays(-1); cookiesDelay[keyDelay].Domain = Config.CookieDomain; //返回連接Cookies清理 var cookiesBackUrl = HttpContext.Current.Response.Cookies; var keyBackUrl = "backurl"; cookiesBackUrl[keyBackUrl].Value = null; cookiesBackUrl[keyBackUrl].Expires = DateTime.Now.AddDays(-1); cookiesBackUrl[keyBackUrl].Domain = Config.CookieDomain; } public static bool IsAuthenticated { get { try { var key = string.Format("{0}.Identity", Config.CookiePrefix); var cookies = HttpContext.Current.Request.Cookies; var keyDelay = string.Format("{0}.Delay", Config.CookiePrefix); var cookiesDelay = HttpContext.Current.Request.Cookies; if (cookies != null && cookiesDelay != null && cookies.AllKeys.Contains(key) && cookiesDelay.AllKeys.Contains(keyDelay)) { HttpContext.Current.Response.Cookies.Remove(keyDelay); HttpContext.Current.Response.Cookies[keyDelay].Value = CreateCookiesValue(DateTime.Now.ToString(), "Delay"); HttpContext.Current.Response.Cookies[keyDelay].Expires = DateTime.Now.AddSeconds(30 * 60); HttpContext.Current.Response.Cookies[keyDelay].Domain = Config.CookieDomain; return true; } else { return false; } } catch (Exception) { return false; } } } }
驗證登陸的Filter:
using System; using System.Collections.Generic; using System.Linq; using System.Web; using System.Web.Mvc; namespace Filters { /// <summary> /// 驗證特性(驗證是否擁登陸) /// </summary> [AttributeUsage(AttributeTargets.Method | AttributeTargets.Class, Inherited = true, AllowMultiple = true)] public class IdentityAuthorizeAttribute : ActionFilterAttribute, IActionFilter { /// <summary> /// Action執行前 /// </summary> /// <param name="filterContext">上下文</param> public override void OnActionExecuting(ActionExecutingContext filterContext) { try { if (!Identity.IsAuthenticated)//沒有登陸的狀況 { HttpContext.Current.Response.Clear(); //TODO:未登陸下的操做,例如跳轉到登陸頁,記錄backUrl等 filterContext.Result = new EmptyResult(); } base.OnActionExecuting(filterContext); } catch (Exception exception) { HttpContext.Current.Response.Clear(); HttpContext.Current.Response.Write(exception.Message); HttpContext.Current.Response.End(); } } } }
在後面代碼的方法前加入該Filter驗證便可在進入方法前驗證登陸;
也可用Identity類中關於用戶登陸信息的操做
PS:轉載請註明出處。