• Asp.Net MVC4网站中自定义AuthorizeAttribute


     
    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。


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

    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中去。

    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方法改变验证规则。

    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上。

    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组

  • 相关阅读:
    GridView中CheckBox,RadioButton并存的同时且有相互关系
    SQL重复记录查询
    TextArea的长度限定
    如何获取程序当前目录
    手机归属地查询
    如何更改ComboBox下拉列表的文字颜色
    世界上主要的一些搜索引擎
    WF/WCF/WCS/WPF/MVC/AJAX/RBAC/SOAP/SCRUM
    .Net Framework 3.5 结构图
    如何打开网页链接
  • 原文地址:https://www.cnblogs.com/wahaccp/p/3331583.html
Copyright © 2020-2023  润新知