• 设为首页
  • 点击收藏
  • 手机版
    手机扫一扫访问
    迪恩网络手机版
  • 关注官方公众号
    微信扫一扫关注
    公众号

Asp.NetMVC4网站中自定义AuthorizeAttribute

原作者: [db:作者] 来自: [db:来源] 收藏 邀请
 
107人阅读 评论(0) 收藏 举报

昨天做了一个例子,是在Mvc4下,对于不同的用户角色(Roles),可以访问不同的页面。根据MVC3中的方式,只需要在相应的Controller上添加上类似于[Authorize(Roles="Admin")]这样的描述就行。后来通过测试发现,如果单独使用[Authorize]或者使用[Authorize(User="xxx")]都是可以的,但是一旦使用[Authorize(Roles="xxx")],就会报数据库连接错误:在 与 SQL Server 建立连接时出现与网络相关的或特定于实例的错误。未找到或无法访问服务器。请验证实例名称是否正确并且 SQL Server 已配置为允许远程连接。 (provider: SQL Network Interfaces, error: 26 - 定位指定的服务器/实例时出错)。在网上查了好多资料,都无法解决,后来我决定自定义AuthorizeAttribute。


首先,应该定义角色,以及用户和角色的对应关系:

 

[csharp] view plaincopy
  1. public enum Roles  
  2. {  
  3.     Admin,  
  4.     PowerManager,  
  5.     User,  
  6.     Guest  
  7. }  
  8.   
  9. public class RolesManager  
  10. {  
  11.     public static List<Roles> GetRoles(string userName)  
  12.     {  
  13.         switch (userName)  
  14.         {  
  15.             case "admin":  
  16.                 return new List<Roles> {Roles.Admin, Roles.PowerManager};  
  17.             case "gqq":  
  18.                 return new List<Roles> {Roles.Admin};  
  19.             default:  
  20.                 return new List<Roles> {Roles.Guest};  
  21.         }  
  22.     }  
  23.   
  24. }  

其次,在登录的时候,就应该把用户的组信息写到验证Cookie中去。

 

[csharp] view plaincopy
  1. <span style="white-space:pre">  </span>[HttpPost]  
  2.        [AllowAnonymous]  
  3.        [ValidateAntiForgeryToken]  
  4.        public ActionResult Login(LoginModel model, string returnUrl)  
  5.        {  
  6.            //是否登录成功,其中AccountBiz.Login是我写的一个static方法,里面是验证用户名、密码的逻辑  
  7.            if (ModelState.IsValid && AccountBiz.Login(model.UserName, model.Password))  
  8.            {  
  9.   
  10.                var roles = string.Join(",", RolesManager.GetRoles(model.UserName).ToArray());  
  11.                //如何用复杂的代码实现登录  
  12.                FormsAuthenticationTicket authTicket = new FormsAuthenticationTicket(1,  
  13.   
  14.                                                                                     model.UserName,  
  15.                                                                                     DateTime.Now,  
  16.                                                                                     DateTime.Now.AddMinutes(20),  
  17.                                                                                     false,  
  18.                                                                                     roles //写入用户角色  
  19.                    );  
  20.                //对authTicket进行加密  
  21.                string encryptedTicket = FormsAuthentication.Encrypt(authTicket);  
  22.   
  23.                //存入cookie  
  24.                var authCookie = new HttpCookie(FormsAuthentication.FormsCookieName, encryptedTicket);  
  25.                System.Web.HttpContext.Current.Response.Cookies.Add(authCookie);  
  26.   
  27.                if (Url.IsLocalUrl(returnUrl) && returnUrl.Length > 1 && returnUrl.StartsWith("/")  
  28.                    && !returnUrl.StartsWith("//") && !returnUrl.StartsWith("/\\"))  
  29.                {  
  30.                    return Redirect(returnUrl);  
  31.                }  
  32.                return RedirectToAction("Index""Home");  
  33.            }  
  34.   
  35.   
  36.            // 如果我们进行到这一步时某个地方出错,则重新显示表单  
  37.            ModelState.AddModelError("""提供的用户名或密码不正确。");  
  38.            return View(model);  
  39.        }  


第三步:自定义继承自AuthorizeAttribute的类ManagerOnlyAttribute,重写AuthorizeCore方法改变验证规则。

 

[csharp] view plaincopy
  1. public class ManagerOnlyAttribute : AuthorizeAttribute  
  2. {  
  3.     // 只需重载此方法,模拟自定义的角色授权机制    
  4.     protected override bool AuthorizeCore(HttpContextBase httpContext)  
  5.     {  
  6.         //获得当前的验证cookie  
  7.         HttpCookie authCookie = httpContext.Request.Cookies[FormsAuthentication.FormsCookieName];  
  8.         //如果当前的cookie为空,则返回。  
  9.         if (authCookie == null || authCookie.Value == "")  
  10.         {  
  11.             return false;  
  12.         }  
  13.         FormsAuthenticationTicket authTicket;  
  14.         try  
  15.         {  
  16.             //对当前的cookie进行解密  
  17.             authTicket = FormsAuthentication.Decrypt(authCookie.Value);  
  18.         }  
  19.         catch  
  20.         {  
  21.             return false;  
  22.         }  
  23.   
  24.         if (authTicket != null)  
  25.         {  
  26.             //和存入时的分隔符有关系,此处存入时的分隔符为逗号  
  27.             var userRoles = authTicket.UserData.Split(new[] {','}).ToList();  
  28.             var roles = Roles.Split(new[] {','}).ToList();  
  29.             return roles.Any(x => userRoles.Contains(x));  
  30.         }  
  31.         return false;  
  32.   
  33.     }  
  34.   
  35. }  


第四步:将自定义的属性描述加在需要访问的Controller或Action上。

 

[csharp] view plaincopy
  1. <strong>    </strong>[ManagerOnly(Roles = "Admin,PowerManager")]  
  2.     public partial class MusicStoreController : Controller  
  3.     {<span style="font-family: Arial, Helvetica, sans-serif;">}</span>  


当我们以admin用户登录,访问http://localhost:8090/MusicStore时,由于admin用户既属于Admin组,也属于PowerManager组,所以可以访问。如果以gqq登录,由于gqq属于Admin组,因此也可以访问该链接(属于Admin、PowerManager中的任意一个组即可)。如果以test用户登录,则该链接不可以访问。(根据上文代码,test属于Guest组


鲜花

握手

雷人

路过

鸡蛋
该文章已有0人参与评论

请发表评论

全部评论

专题导读
热门推荐
热门话题
阅读排行榜

扫描微信二维码

查看手机版网站

随时了解更新最新资讯

139-2527-9053

在线客服(服务时间 9:00~18:00)

在线QQ客服
地址:深圳市南山区西丽大学城创智工业园
电邮:jeky_zhao#qq.com
移动电话:139-2527-9053

Powered by 互联科技 X3.4© 2001-2213 极客世界.|Sitemap