通常状况下,在咱们作访问权限管理的时候,会把用户的正确登陆后的基本信息保存在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以下:
1 public ActionResult Login(string uname) 2 { 3 if (!string.IsNullOrEmpty(uname)) 4 { 5 //FormsAuthentication.SetAuthCookie(uname,true); 6 FormsAuthenticationTicket ticket = new FormsAuthenticationTicket 7 ( 1, 8 uname, 9 DateTime.Now, 10 DateTime.Now.AddMinutes(20), 11 true, 12 "7,1,8", 13 "/" 14 ); 15 var cookie = new HttpCookie(FormsAuthentication.FormsCookieName,FormsAuthentication.Encrypt(ticket)); 16 cookie.HttpOnly = true; 17 HttpContext.Response.Cookies.Add(cookie); 18 19 return RedirectToAction("UserPage"); 20 } 21 return RedirectToAction("Index"); 22 }
这里FormsAuthenticationTicket 第六个参数存储的是string 类型的userData ,这里就存放当前用户的角色ID,以英文逗号分隔。
当使用用户名 “测试” 登陆后,客户端就会出现这样一条记录Cookie
二、获取认证信息
登陆后,在内容页,咱们能够经过,当前请求的User.Identity.Name 获取到uname信息,也能够经过读取Request 中的Cookie 解密,获取到Ticket,再从其中获取uname 和 userData (也就是以前存储的角色ID信息)。
1 ViewData["user"]=User.Identity.Name; 2 3 var cookie = Request.Cookies[FormsAuthentication.FormsCookieName]; 4 var ticket = FormsAuthentication.Decrypt(cookie.Value); 5 string role = ticket.UserData; 6 7 ViewData["role"] = role; 8 return View();
三、经过注解属性,实现权限访问控制
在web.config中配置启用Form认证 和 角色管理
1 <authentication mode="Forms"> 2 <forms loginUrl="~/Login/Index" timeout="2880" /> 3 </authentication> 4 <roleManager enabled="true" defaultProvider="CustomRoleProvid"> 5 <providers> 6 <clear/> 7 <add name="CustomRoleProvid" type="MvcApp.Helper.CustomRoleProvider"/> 8 </providers> 9 </roleManager>
当咱们在Controller 、Action添加注解属性时候,设置的Role是从哪里获得的呢?由于没有使用基于Membership的那一套authentication,这里咱们还要建立一个自定义的RoleProvider 。名称为CustomRoleProvider ,继承自 RoleProvider。这里是在MVCApp下面的Helper文件夹中建立了本身的CustomRoleProvider.cs文件。
RoleProvider中有不少abstract 方法,咱们具体只实现其中的GetRolesForUser 方法用于获取用户角色。这里的用户角色,咱们能够根据拿到的用户Id从数据库查询,或者拿取Session中存储了的、或是Cookie中存储了的。这里我前面已经把Role存储在Ticket的userData中了,那就从Ticket中获取吧。
1 public override string[] GetRolesForUser(string username) 2 { 3 var cookie = HttpContext.Current.Request.Cookies[FormsAuthentication.FormsCookieName]; 4 var ticket = FormsAuthentication.Decrypt(cookie.Value); 5 string role = ticket.UserData; 6 return role.Split(','); 7 }
在须要,验证的Controller、Action上面添加注解属性,好比这个Action 只容许RoleID 为包含1或2或3的访问,而当前用户RoleID为(七、一、8)就是用户有权访问了。
1 [Authorize(Roles="1,2,3")] 2 public ActionResult Role() 3 { 4 ViewData["user"] = User.Identity.Name; 5 return View(); 6 }
注:一、Ticket存储在在Cookie过时时间,和关闭浏览器是否在记住当前票据,在FormsAuthenticationTicket实例化时候能够设置参数,
二、Role 的获取能够不要存储在ticket 的userData中,能够直接从数据库读取,userData能够存储其余信息。
三、要想灵活配置Controller 和Action的 容许访问的Role 能够自定义AuthorizeAttribute override里面的OnAuthorization方法,在该方法中
读取当前页面容许访问的角色ID,根据当前用户的RoleID,进行检查。这样也就实现了,Role的灵活配置。
四、Ticket中的信息,最终仍是存储在cookie中,安全性方面仍是本身斟酌吧,我的以为仍是把UserID和RoleID存储在Session中的比较好。