六狼论坛

 找回密码
 立即注册

QQ登录

只需一步,快速开始

新浪微博账号登陆

只需一步,快速开始

搜索
查看: 618|回复: 0

asp.net MVC 权限设计(续)

[复制链接]
 楼主| 发表于 2012-10-9 00:24:42 | 显示全部楼层 |阅读模式
asp.net MVC 权限设计一文中没有demo放出来,应大家的要求,这里补充上文并放出demo。

几点说明:
    1、基于将角色与controller、action相关联来判断用户是否有权
    2、通过自定义AuthorizeAttribute实现
    3、demo 仅供参考,一些规则可以根据实际情况重新定义

简明需求
1、可以对每个action实现权限控制,并且可以在数据库动态配置
2、权限分为允许所有人访问、允许注册用户访问、允许\禁止特定角色人访问

数据库设计

在demo里不使用数据库,这里给出表对应的类
View Code?
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
/// <SUMMARY>
    /// 控制器和Action
    /// </SUMMARY>
    public class ControllerAction
    {
        public int Id
        {
            get;
            set;
        }
  
        public string Name
        {
            get;
            set;
        }
  
        /// <SUMMARY>
        /// IsController是指是否是controller,如果为false,
        /// 表示是action,那么controllerName字段就派上用场了
        /// </SUMMARY>
        public bool IsController
        {
            get;
            set;
        }
  
        /// <SUMMARY>
        /// 控制器名称
        /// 如果IsController为false,该项不能为空
        /// </SUMMARY>
        public string ControllName
        {
            get;
            set;
        }
  
        /// <SUMMARY>
        /// 是指是否允许没有权限的人访问  
        /// </SUMMARY>
        public bool IsAllowedNoneRoles
        {
            get;
            set;
        }
  
        /// <SUMMARY>
        /// 是否允许有角色的人访问  
        /// </SUMMARY>
        public bool IsAllowedAllRoles
        {
            get;
            set;
        }
    }
  
    /// <SUMMARY>
    /// 用户与角色的关联表
    /// </SUMMARY>
    public class ControllerActionRole
    {
        public int Id
        {
            get;
            set;
        }
  
        /// <SUMMARY>
        /// 对应的ControllerAction编号
        /// </SUMMARY>
        public int ControllerActioId
        {
            get;
            set;
        }
  
        /// <SUMMARY>
        /// 对应的角色编号
        /// </SUMMARY>
        public int RoleId
        {
            get;
            set;
        }
  
        /// <SUMMARY>
        /// IsAllowed表示包含RoleId的用户是否有权限访问ControllerActioId
        /// </SUMMARY>
        public bool IsAllowed
        {
            get;
            set;
        }
    }
  
    /// <SUMMARY>
    /// 角色
    /// </SUMMARY>
    public class Role
    {
        public int Id
        {
            get;
            set;
        }
  
        public string Name
        {
            get;
            set;
        }
  
        public string Description
        {
            get;
            set;
        }
    }
  
    /// <SUMMARY>
    /// 用户
    /// </SUMMARY>
    public class User
    {
        public int Id
        {
            get;
            set;
        }
  
        public string Name
        {
            get;
            set;
        }
    }
  
    /// <SUMMARY>
    /// 用户与角色的关联表
    /// </SUMMARY>
    public class UserRole
    {
        public int Id
        {
            get;
            set;
        }
        public int UserId
        {
            get;
            set;
        }
        public int RoleId
        {
            get;
            set;
        }
    }




核心流程

我们见一个Database类来模拟数据库
View Code?
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
/// <SUMMARY>
       /// <SUMMARY>
    /// 模拟数据库
    /// </SUMMARY>
    public class Database
    {
        public static List<USER> Users;
        public static List<ROLE> Roles;
        public static List<USERROLE> UserRoles;
        public static List<CONTROLLERACTION> ControllerActions;
        public static List<CONTROLLERACTIONROLE> ControllerActionRoles;
  
        static Database()
        {
            // 初始化用户
            Users = new List<USER>()
            {
                new User(){Id=1,Name="Admin"},
                new User(){Id=2,Name ="User"},
                new User(){Id=3,Name="Guest"}
            };
  
            Roles = new List<ROLE>()
            {
                new Role() {Id=1,Name="Administrator"},
                new Role() {Id=2,Name="User"}
            };
  
            UserRoles = new List<USERROLE>()
            {
                 new UserRole(){Id=1,RoleId=1,UserId=1}, //管理员
                 new UserRole(){Id=2,RoleId=2,UserId=2} //用户
            };
  
            ControllerActions = new List<CONTROLLERACTION>()
            {
                new ControllerAction(){Id=1,Name="Index",IsController=true,IsAllowedNoneRoles=true,IsAllowedAllRoles=true}, // /Home 允许所有人访问
  
                new ControllerAction(){Id=2,ControllName="Home",Name="Admin",IsController=false,IsAllowedNoneRoles=false,IsAllowedAllRoles = false}, // /Home/Admin 管理员才能访问
  
                new ControllerAction(){Id=3,ControllName="Home",Name="User",IsController=false,IsAllowedNoneRoles=false,IsAllowedAllRoles = true}, // /Home/User 有角色的人才能访问
                  
                new ControllerAction(){Id=4,ControllName="Home",Name="UserOnly",IsController=false,IsAllowedNoneRoles=false,IsAllowedAllRoles = false}, // /Home/UserOnly 用户才能访问
  
            };
  
            ControllerActionRoles = new List<CONTROLLERACTIONROLE>() {  
                new ControllerActionRole(){ Id=1,ControllerActioId = 2,RoleId = 1,IsAllowed = true },  // 管理员才能访问
                new ControllerActionRole(){ Id=2,ControllerActioId = 4,RoleId = 2,IsAllowed = true }  // USER才能访问
            };
  
        }
    }
  </CONTROLLERACTIONROLE></CONTROLLERACTION></USERROLE></ROLE></USER></CONTROLLERACTIONROLE></CONTROLLERACTION></USERROLE></ROLE></USER></SUMMARY>




来看我们的主要代码
?
  /// <SUMMARY>
/// 自定义AuthorizeAttribute
/// </SUMMARY>
public class UserAuthorizeAttribute : AuthorizeAttribute
{

    public override void OnAuthorization(AuthorizationContext filterContext)
    {
        var user = filterContext.HttpContext.Session["CurrentUser"] as User;

        // 用户为空,赋予Guest
        if (user == null)
        {
            user = Database.Users.Find(u => u.Name == "Guest");
        }

        var controller = filterContext.RouteData.Values["controller"].ToString();
        var action = filterContext.RouteData.Values["action"].ToString();
        var isAllowed = this.IsAllowed(user, controller, action);

        if (!isAllowed)
        {
            filterContext.RequestContext.HttpContext.Response.Write("无权访问");
            filterContext.RequestContext.HttpContext.Response.End();
        }

    }

    /// <SUMMARY>
    /// 判断是否允许访问
    /// </SUMMARY>
    /// <SPAN name="user"> </SPAN>用户
    /// <SPAN name="controller"> </SPAN>控制器
    /// <SPAN name="action"> </SPAN>action
    /// <RETURNS>是否允许访问</RETURNS>
    public bool IsAllowed(User user, string controller, string action)
    {

        // 找controllerAction
        var controllerAction = Database.ControllerActions.Find(ca => ca.IsController == false && ca.Name == action && ca.ControllName == controller);

        //action无记录,找controller
        if (controllerAction == null)
        {
            controllerAction = Database.ControllerActions.Find(ca => ca.IsController && ca.Name == controller);
        }

        // 无规则
        if (controllerAction == null)
        {
            return true;
        }


        // 允许没有角色的:也就是说允许所有人,包括没有登录的用户  
        if (controllerAction.IsAllowedNoneRoles)
        {
            return true;
        }

        // 允许所有角色:只要有角色,就可以访问  
        if (controllerAction.IsAllowedAllRoles)
        {
            var roles = Database.UserRoles.FindAll(ur => ur.UserId == user.Id);
            if (roles.Count > 0)
            {
                return true;
            }
            else
            {
                return false;
            }
        }


        // 选出action对应的角色  
        var actionRoles = Database.ControllerActionRoles.FindAll(ca => ca.ControllerActioId == controllerAction.Id).ToList();

        if (actionRoles.Count == 0)
        {
            // 角色数量为0,也就是说没有定义访问规则,默认允许访问  
            return true;
        }

        var userHavedRolesids = Database.UserRoles.FindAll(ur => ur.UserId == user.Id).Select(ca => ca.RoleId).ToList();

        // 查找禁止的角色  
        var notAllowedRoles = actionRoles.FindAll(r => !r.IsAllowed).Select(ca => ca.RoleId).ToList();
        if (notAllowedRoles.Count > 0)
        {
            foreach (int roleId in notAllowedRoles)
            {
                // 用户的角色在禁止访问列表中,不允许访问  
                if (userHavedRolesids.Contains(roleId))
                {
                    return false;
                }
            }
        }

        // 查找允许访问的角色列表  
        var allowRoles = actionRoles.FindAll(r => r.IsAllowed).Select(ca => ca.RoleId).ToList();
        if (allowRoles.Count > 0)
        {
            foreach (int roleId in allowRoles)
            {
                // 用户的角色在访问的角色列表  
                if (userHavedRolesids.Contains(roleId))
                {
                    return true;
                }
            }
        }

        // 默认禁止访问
        return false;
    }

}



测试?
[HandleError]
[UserAuthorize]
public class HomeController : Controller
{
    public ActionResult Index()
    {
        ViewData["Message"] = "欢迎使用 ASP.NET MVC!";

        return View();
    }
    public ActionResult Admin()
    {
        ViewData["Message"] = "只有管理员才能访问!";

        return View("Index");
    }
    public ActionResult User()
    {
        ViewData["Message"] = "只要是注册用户就能访问!";

        return View("Index");
    }
    public ActionResult UserOnly()
    {
        ViewData["Message"] = "只能是User才能能访问!";

        return View("Index");
    }

    public ActionResult Login(string user)
    {
        Session["CurrentUser"] = Database.Users.Find(u => u.Name == user);
        if (Session["CurrentUser"] != null)
        {
            ViewData["Message"] = "你已登录为" + user;
        }

        return View("Index");
    }


    public ActionResult About()
    {
        return View();
    }
}






1、登录为Admin

访问Admin


访问User


访问UserOnly


2、登录为User

访问Admin


访问User

访问UserOnly


demo下载 MVCRole.rar
本文摘自:http://www.cnblogs.com/xiaoqi/archive/2011/01/24/1942880.html
该会员没有填写今日想说内容.
您需要登录后才可以回帖 登录 | 立即注册 新浪微博账号登陆

本版积分规则

快速回复 返回顶部 返回列表