前言 昨天和一個技術比較好的前輩聊了聊,發現有的時候自己的學習方式有些問題,不知道有沒有和我一樣的越學習越感覺到知識的匱乏不過能認識到這個問題的同學們,也不要太心急路是一步一步走的飯是一口一口吃的認識到錯誤才能更高的改進錯誤,腳踏實地只要有上勁學習的心,終會有所成就。認識到自己薄弱的地方進行學習,要 ...
前言
昨天和一個技術比較好的前輩聊了聊,發現有的時候自己的學習方式有些問題,不知道有沒有和我一樣的越學習越感覺到知識的匱乏不過能認識到這個問題的同學們,也不要太心急路是一步一步走的飯是一口一口吃的認識到錯誤才能更高的改進錯誤,腳踏實地只要有上勁學習的心,終會有所成就。認識到自己薄弱的地方進行學習,要清楚學習的目的呀調理清晰:這個是什麼?為什麼要這樣?能解決什麼問題?入正題吧。
什麼是身份驗證
很多網站都有登錄對話框,讓事先已經註冊的用戶驗證,以便為他們提供個性化的服務等。可以把這個過程看作是兩件事情的發生:驗證和授權!登陸的作用是驗證請求登陸的用戶是否合法,而授權則是驗證合法的用戶在請求資源時,根據他們的許可權決定是訪問還是拒絕。
舉個例子:我們已經在一個網站上登錄了,你剛把網頁關閉發現又要使用這個網站於是乎你又打開了瀏覽器然後輸入了網址,這個時候你發現還要讓你登錄才能進行操作。頻繁的這樣是失去用戶極大的體驗效果所以這個時候就用到了身份驗證。
身份驗證是什麼?驗證和授權。為什麼要使用?加強用戶體驗效果。能解決什麼問題?節省用戶時間避免重覆性動作。
Form身份驗證思路
用戶要瀏覽需要許可權的頁面,此時,安全機制先啟動,檢查當前用戶請求是否持有用戶票據的Cookie如此Cookie存在:解析Cookie中的票據信息,獲得用戶角色,創建用戶標識或者對象。否則:認為用戶無權瀏覽該頁面,跳轉至登入頁面,登入成功後重定向到所請求頁面。
建立BaseController
建立BaseController繼承Controller,然後在其他Controller中用BaseController作為父類來繼承。我們在Base中實現From設置Ticket和寫入Cooike信息等操作。
/// <summary> /// 保存用戶登陸信息 /// </summary> public void WriteUserInfoToCookie(UserInfo userinfo) { var jss = new JavaScriptSerializer(); var logonInfo = jss.Serialize(userinfo); //設置Ticket信息 var ticket = new FormsAuthenticationTicket(1, userinfo.Name, DateTime.Now, DateTime.Now.AddDays(1), false, logonInfo); //加密驗證票據 var strTicket = FormsAuthentication.Encrypt(ticket); //保存cookie SetCookie(FormsAuthentication.FormsCookieName, strTicket, ticket.Expiration, true); } /// <summary> /// 寫入Cooike /// </summary> /// <param name="cookiename"></param> /// <param name="value"></param> /// <param name="expires"></param> /// <param name="isSetExpires"></param> public static void SetCookie(string cookiename, string value, DateTime expires, bool isSetExpires) { var request = System.Web.HttpContext.Current.Request; var response = System.Web.HttpContext.Current.Response; var cookie = request.Cookies[cookiename] ?? new System.Web.HttpCookie(cookiename); cookie.Domain = FormsAuthentication.CookieDomain; if (value == null) { RemoveCookie(cookiename); } else { cookie.Value = value; //true代表客戶端只能讀,不能寫。只有服務端可寫,防止被篡改 cookie.HttpOnly = true; if (isSetExpires) { cookie.Expires = expires; } } response.Cookies.Add(cookie); } /// <summary> /// 移除指定名稱的cookie對象中的集合對 /// </summary> /// <param name="cookieName">cookie名稱</param> public static void RemoveCookie(string cookieName) { var cookie = System.Web.HttpContext.Current.Request.Cookies[cookieName]; var response = System.Web.HttpContext.Current.Response; if (cookie == null) return; cookie.Values.Clear(); cookie.Domain = FormsAuthentication.CookieDomain; cookie.Expires = DateTime.Now.AddDays(-10000d); response.Cookies.Add(cookie); }
建立實體作為用戶登錄信息和寫入Cookie
public class UserInfo { public string Name { get; set; } public string PassWord { get; set; } }
配置WebConfig
<system.web> <authentication mode="Forms"> <forms name="test" protection="All" loginUrl="~/account/default" timeout="2880" /> </authentication> </system.web>
Forms Authentication相關的配置
有些同學會蒙圈為啥會配置authentication,下麵我們看下他們的信息
在web.config文件中,<system.web>/<authentication>配置節用於對驗證進行配置。為<authentication>節點提供mode="Forms"屬性可以啟用Forms Authentication。一個典型的<authentication>配置節如下所示:
<authentication mode="Forms"> <forms name=".ASPXAUTH" loginUrl="login.aspx" defaultUrl="default.aspx" protection="All" timeout="30" path="/" requireSSL="false" slidingExpiration="false" enableCrossAppRedirects="false" cookieless="UseDeviceProfile" domain="" /> </authentication>
以上代碼使用的均是預設設置,換言之,如果你的哪項配置屬性與上述代碼一致,則可以省略該屬性。例如<forms name="MyAppAuth" />。下麵依次介紹一下各種屬性:
- name——Cookie的名字。Forms Authentication可能會在驗證後將用戶憑證放在Cookie中,name屬性決定了該Cookie的名字。通過FormsAuthentication.FormsCookieName屬性可以得到該配置值(稍後介紹FromsAuthentication類)。
- loginUrl——登錄頁的URL。通過FormsAuthentication.LoginUrl屬性可以得到該配置值。當調用FormsAuthentication.RedirectToLoginPage()方法時,客戶端請求將被重定向到該屬性所指定的頁面。loginUrl的預設值為“login.aspx”,這表明即便不提供該屬性值,ASP.NET也會嘗試到站點根目錄下尋找名為login.aspx的頁面。
- defaultUrl——預設頁的URL。通過FormsAuthentication.DefaultUrl屬性得到該配置值。
- protection——Cookie的保護模式,可取值包括All(同時進行加密和數據驗證)、Encryption(僅加密)、Validation(僅進行數據驗證)和None。為了安全,該屬性通常從不設置為None。
- timeout——Cookie的過期時間。
- path——Cookie的路徑。可以通過FormsAuthentication.FormsCookiePath屬性得到該配置值。
- requireSSL——在進行Forms Authentication時,與伺服器交互是否要求使用SSL。可以通過FormsAuthentication.RequireSSL屬性得到該配置值。
- slidingExpiration——是否啟用“彈性過期時間”,如果該屬性設置為false,從首次驗證之後過timeout時間後Cookie即過期;如果該屬性為true,則從上次請求該開始過timeout時間才過期,這意味著,在首次驗證後,如果保證每timeout時間內至少發送一個請求,則Cookie將永遠不會過期。通過FormsAuthentication.SlidingExpiration屬性可以得到該配置值。
- enableCrossAppRedirects——是否可以將以進行了身份驗證的用戶重定向到其他應用程式中。通過FormsAuthentication.EnableCrossAppRedirects屬性可以得到該配置值。為了安全考慮,通常總是將該屬性設置為false。
- cookieless——定義是否使用Cookie以及Cookie的行為。Forms Authentication可以採用兩種方式在會話中保存用戶憑據信息,一種是使用Cookie,即將用戶憑據記錄到Cookie中,每次發送請求時瀏覽器都會將該Cookie提供給伺服器。另一種方式是使用URI,即將用戶憑據當作URL中額外的查詢字元串傳遞給伺服器。該屬性有四種取值——UseCookies(無論何時都使用Cookie)、UseUri(從不使用Cookie,僅使用URI)、AutoDetect(檢測設備和瀏覽器,只有當設備支持Cookie並且在瀏覽器中啟用了Cookie時才使用Cookie)和UseDeviceProfile(只檢測設備,只要設備支持Cookie不管瀏覽器是否支持,都是用Cookie)。通過FormsAuthentication.CookieMode屬性可以得到該配置值。通過FormsAuthentication.CookiesSupported屬性可以得到對於當前請求是否使用Cookie傳遞用戶憑證。
- domain——Cookie的域。通過FormsAuthentication.CookieDomain屬性可以得到該配置值。
驗證Ing
我們創建個Controller,我建立的是HomeController來進行測試
public class HomeController : BaseCntroller { public ActionResult Index() { if (User.Identity.IsAuthenticated) { var strUser = ((FormsIdentity)User.Identity).Ticket.UserData; var _loginInfo = new UserInfo(); if (strUser.Contains("{") && strUser.Contains("}")) { var jss = new JavaScriptSerializer(); _loginInfo = jss.Deserialize<UserInfo>(strUser); } else { //或者可以從緩存裡面取出 } return Json(new { result = true }); } else { UserInfo user = new UserInfo(); user.Name = "焦海濤"; user.PassWord = "123456"; WriteUserInfoToCookie(user); } return View(); } }
剛進來我們可以看到User的identity是flase說明我們沒有登錄過。那麼肯定是else來進行寫入我們的信息。
設置tick信息然後進行寫入cooike
瀏覽器中可以看到我們使用的Cooike,這就是我們剛剛添加的。