通常狀況下,在咱們作訪問權限管理的時候,會把用戶的正確登陸後的基本信息保存在Session中,之後用戶每次請求頁面或接口數據的時候,拿到web
Session中存儲的用戶基本信息,查看比較他有沒有登陸和可否訪問當前頁面。數據庫
Session的原理,也就是在服務器端生成一個SessionID對應了存儲的用戶數據,而SessionID存儲在Cookie中,客戶端之後每次請求都會帶上這個瀏覽器
Cookie,服務器端根據Cookie中的SessionID找到存儲在服務器端的對應當前用戶的數據。安全
FormsAuthentication是微軟提供給咱們開發人員使用,作身份認證使用的。經過該認證,咱們能夠把用戶Name 和部分用戶數據存儲在Cookie中,服務器
經過基本的條件設置能夠,很簡單的實現基本的身份角色認證。cookie
這裏要實現的效果是:在不使用membership的狀況下,使用系統提供的Authorize 實現基於角色的訪問控制。ide
一、建立認證信息 Ticket 測試
在用戶登陸之後,把用戶的ID和對應的角色(多個角色用,分隔),存儲在Ticket中。加密
使用FormsAuthentication.Encrypt 加密票據。spa
把加密後的Ticket 存儲在Response Cookie中(客戶端js不須要讀取到這個Cookie,因此最好設置HttpOnly=True,防止瀏覽器攻擊竊取、僞造Cookie)。這樣下次能夠從Request Cookie中讀取了。
一個簡單的Demo以下:
public ActionResult Login(string uname) { if (!string.IsNullOrEmpty(uname)) { //FormsAuthentication.SetAuthCookie(uname,true);
FormsAuthenticationTicket ticket = new FormsAuthenticationTicket ( 1, uname, DateTime.Now, DateTime.Now.AddMinutes(20), true, "7,1,8", "/" ); var cookie = new HttpCookie(FormsAuthentication.FormsCookieName,FormsAuthentication.Encrypt(ticket)); cookie.HttpOnly = true; HttpContext.Response.Cookies.Add(cookie); return RedirectToAction("UserPage"); } return RedirectToAction("Index"); }
這裏FormsAuthenticationTicket 第六個參數存儲的是string 類型的userData ,這裏就存放當前用戶的角色ID,以英文逗號分隔。
當使用用戶名 「測試」 登陸後,客戶端就會出現這樣一條記錄Cookie
二、獲取認證信息
登陸後,在內容頁,咱們能夠經過,當前請求的User.Identity.Name 獲取到uname信息,也能夠經過讀取Request 中的Cookie 解密,獲取到Ticket,再從其中獲取uname 和 userData (也就是以前存儲的角色ID信息)。
ViewData["user"]=User.Identity.Name; var cookie = Request.Cookies[FormsAuthentication.FormsCookieName]; var ticket = FormsAuthentication.Decrypt(cookie.Value); string role = ticket.UserData; ViewData["role"] = role; return View();
三、經過註解屬性,實現權限訪問控制
在web.config中配置啓用Form認證 和 角色管理
<authentication mode="Forms">
<forms loginUrl="~/Login/Index" timeout="2880" />
</authentication>
<roleManager enabled="true" defaultProvider="CustomRoleProvid">
<providers>
<clear/>
<add name="CustomRoleProvid" type="MvcApp.Helper.CustomRoleProvider"/>
</providers>
</roleManager>
當咱們在Controller 、Action添加註解屬性時候,設置的Role是從哪裏獲得的呢?由於沒有使用基於Membership的那一套authentication,這裏咱們還要建立一個自定義的RoleProvider 。名稱爲CustomRoleProvider ,繼承自 RoleProvider。這裏是在MVCApp下面的Helper文件夾中建立了本身的CustomRoleProvider.cs文件。
RoleProvider中有不少abstract 方法,咱們具體只實現其中的GetRolesForUser 方法用於獲取用戶角色。這裏的用戶角色,咱們能夠根據拿到的用戶Id從數據庫查詢,或者拿取Session中存儲了的、或是Cookie中存儲了的。這裏我前面已經把Role存儲在Ticket的userData中了,那就從Ticket中獲取吧。
public override string[] GetRolesForUser(string username) { var cookie = HttpContext.Current.Request.Cookies[FormsAuthentication.FormsCookieName]; var ticket = FormsAuthentication.Decrypt(cookie.Value); string role = ticket.UserData; return role.Split(','); }
在須要,驗證的Controller、Action上面添加註解屬性,好比這個Action 只容許RoleID 爲包含1或2或3的訪問,而當前用戶RoleID爲(七、一、8)就是用戶有權訪問了。
[Authorize(Roles="1,2,3")] public ActionResult Role() { ViewData["user"] = User.Identity.Name; return View(); }
P.S. :一、Ticket存儲在在Cookie過時時間,和關閉瀏覽器是否在記住當前票據,在FormsAuthenticationTicket實例化時候能夠設置參數,
二、Role 的獲取能夠不要存儲在ticket 的userData中,能夠直接從數據庫讀取,userData能夠存儲其餘信息。
三、要想靈活配置Controller 和Action的 容許訪問的Role 能夠自定義AuthorizeAttribute override裏面的OnAuthorization方法,在該方法中
讀取當前頁面容許訪問的角色ID,根據當前用戶的RoleID,進行檢查。這樣也就實現了,Role的靈活配置。
四、Ticket中的信息,最終仍是存儲在cookie中,安全性方面仍是本身斟酌吧,我的以爲仍是把UserID和RoleID存儲在Session中的比較好。