MVC3的Controller和Action可以实现加一个[Authorize]的方式来验证,非常简洁,如:[Authorize(Users = "abc")],[Authorize(Roles = "user")]那么它是怎么实现的呢?
很简单,Authorize标签还是基于Forms验证的,验证用户非常简单,只要你请求页面的时候cookie里面有.net的验证票据(代码段1),它就会生成一个User对象,而User对象,就是一个GenericPrincipal对象:
首先,刚才说了,有验证票据只要User对象会生成,意味着User.Identity.IsAuthenticated肯定是true,即有验证票则为验证通过
其次,User.Identity.Name由生成票据的时候的name参数决定,并且也是[Authorize(Users = "abc")]这个验证规则中,User验证的对象。
而验证角色就没那么简单了,相关详细说明可参考这篇文章,简单来说,就是在从票据生成User对象的时候,角色数据是不会自动生成的,所以上面提到的这篇文章解决的就是如何让User对象具有角色属性,一旦这个属性有了,[Authorize(Roles = "user")]这种标签就可以自动工作了,我们采用的做法是把角色信息保存到验证票据里面,在页面请求后的验证请求事件里,从验证票据里面把角色提取出来,然后用带角色的构造函数重新实例化这个User对象(代码段2)
代码段1
1: public static void SaveLoginInfo(string userid, string userdata, bool remember)
2: {
3: DateTime expiration = remember ? DateTime.Now.AddMonths(3) : DateTime.Now.AddMinutes(30);//这是为了实现记住密码,与本例无关
4: FormsAuthenticationTicket authTicket = new FormsAuthenticationTicket(
5: 1,//version
6: userid,//user name,此处就是用于用户验证的用户名
7: System.DateTime.Now,//login time
8: expiration,// Expiration
9: true,//persistent
10: userdata//把角色信息存于此,比如admin,superadmin
11: );
12: //Entrcy Ticket
13: string entrcyedTicket = FormsAuthentication.Encrypt(authTicket);
14: HttpCookie authCookie = new HttpCookie(FormsAuthentication.FormsCookieName, entrcyedTicket);
15: authCookie.Expires = expiration;
16: HttpContext.Current.Response.Cookies.Add(authCookie);
17: }
代码段2
1: protected void Application_AuthenticateRequest()
2: {
3: //判断正在请求页的用户的身份验证信息是否为空
4: if (HttpContext.Current.User != null)
5: {
6: //判断用户是否已经进行了身份验证
7: if (HttpContext.Current.User.Identity.IsAuthenticated)
8: {
9: //判断当前用户身份验证的方式是否为Forms身份验证方式
10: if (HttpContext.Current.User.Identity is FormsIdentity)
11: {
12: //获得进行了Forms身份验证的用户标识
13: FormsIdentity UserIdent = (FormsIdentity)(HttpContext.Current.User.Identity);
14: //从身份验证票中获得用户数据
15: string UserData = UserIdent.Ticket.UserData;
16: //分割用户数据得到用户角色数组
17: string[] roles = UserData.Split(',');
18: //从用户标识和角色组初始化GenericPrincipal类
19: HttpContext.Current.User = new System.Security.Principal.GenericPrincipal(UserIdent, roles);
20: }
21: }
22: }
23: }