基於FormsAuthentication的用戶、角色身份認證

       通常狀況下,在咱們作訪問權限管理的時候,會把用戶的正確登陸後的基本信息保存在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中的比較好。

相關文章
相關標籤/搜索