|
一般情況下,在我們做訪問權(quán)限管理的時候,會把用戶的正確登錄后的基本信息保存在Session中,以后用戶每次請求頁面或接口數(shù)據(jù)的時候,拿到 Session中存儲的用戶基本信息,查看比較他有沒有登錄和能否訪問當(dāng)前頁面。 Session的原理,也就是在服務(wù)器端生成一個SessionID對應(yīng)了存儲的用戶數(shù)據(jù),而SessionID存儲在Cookie中,客戶端以后每次請求都會帶上這個 Cookie,服務(wù)器端根據(jù)Cookie中的SessionID找到存儲在服務(wù)器端的對應(yīng)當(dāng)前用戶的數(shù)據(jù)。 FormsAuthentication是微軟提供給我們開發(fā)人員使用,做身份認(rèn)證使用的。通過該認(rèn)證,我們可以把用戶Name 和部分用戶數(shù)據(jù)存儲在Cookie中, 通過基本的條件設(shè)置可以,很簡單的實現(xiàn)基本的身份角色認(rèn)證。 這里要實現(xiàn)的效果是:在不使用membership的情況下,使用系統(tǒng)提供的Authorize 實現(xiàn)基于角色的訪問控制。 1、創(chuàng)建認(rèn)證信息 Ticket 在用戶登錄以后,把用戶的ID和對應(yīng)的角色(多個角色用,分隔),存儲在Ticket中。 使用FormsAuthentication.Encrypt 加密票據(jù)。 把加密后的Ticket 存儲在Response Cookie中(客戶端js不需要讀取到這個Cookie,所以最好設(shè)置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 第六個參數(shù)存儲的是string 類型的userData ,這里就存放當(dāng)前用戶的角色I(xiàn)D,以英文逗號分隔。 當(dāng)使用用戶名 “測試” 登錄后,客戶端就會出現(xiàn)這樣一條記錄Cookie
2、獲取認(rèn)證信息 登錄后,在內(nèi)容頁,我們可以通過,當(dāng)前請求的User.Identity.Name 獲取到uname信息,也可以通過讀取Request 中的Cookie 解密,獲取到Ticket,再從其中獲取uname 和 userData (也就是之前存儲的角色I(xiàn)D信息)。 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();3、通過注解屬性,實現(xiàn)權(quán)限訪問控制 在web.config中配置啟用Form認(rèn)證 和 角色管理 <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>當(dāng)我們在Controller 、Action添加注解屬性時候,設(shè)置的Role是從哪里得到的呢?因為沒有使用基于Membership的那一套authentication,這里我們還要創(chuàng)建一個自定義的RoleProvider 。名稱為CustomRoleProvider ,繼承自 RoleProvider。這里是在MVCApp下面的Helper文件夾中創(chuàng)建了自己的CustomRoleProvider.cs文件。 RoleProvider中有很多abstract 方法,我們具體只實現(xiàn)其中的GetRolesForUser 方法用于獲取用戶角色。這里的用戶角色,我們可以根據(jù)拿到的用戶Id從數(shù)據(jù)庫查詢,或者拿取Session中存儲了的、或是Cookie中存儲了的。這里我前面已經(jīng)把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的訪問,而當(dāng)前用戶RoleID為(7、1、8)就是用戶有權(quán)訪問了。 [Authorize(Roles="1,2,3")]
public ActionResult Role()
{
ViewData["user"] = User.Identity.Name;
return View();
} 2、Role 的獲取可以不要存儲在ticket 的userData中,可以直接從數(shù)據(jù)庫讀取,userData可以存儲其他信息。 3、要想靈活配置Controller 和Action的 允許訪問的Role 可以自定義AuthorizeAttribute override里面的OnAuthorization方法,在該方法中 讀取當(dāng)前頁面允許訪問的角色I(xiàn)D,根據(jù)當(dāng)前用戶的RoleID,進(jìn)行檢查。這樣也就實現(xiàn)了,Role的靈活配置。 4、Ticket中的信息,最終還是存儲在cookie中,安全性方面還是自己斟酌吧,個人覺得還是把UserID和RoleID存儲在Session中的比較好。 |
|
|