aspMVC权限设计
⼏点说明:
1、该权限系统是个⽹站⽤的,⽤户简单,因此不涉及到部门这些信息
2、基于将⾓⾊与controller、action相关联来判断⽤户是否有权
3、通过重载AuthorizeAttribute实现
数据库设计:
表说明
ControllerAction
1. Name是controller的名称
2. IsController是指是否是controller,如果为false,表⽰存的是action,那么controllerName字段就派上⽤场了
3. IsAllowedNoneRoles是指是否允许没有权限的⼈访问
4. IsAllowedAllRoles是指是否允许有⾓⾊的⼈访问
IsAllowedNoneRoles,IsAllowedAllRoles实现了允许所有⼈访问以及允许所有注册⽤户访问:),并且我们约定,IsAllowedNoneRoles具有最⾼的优先级,其次是IsAllowedAllRoles,然后才是ControllerActionRole中定义的规则
ControllerActionRole
IsAllowed表⽰该action或者controller是否允许访问,加⼊表中有两条记录
⾓⾊Name ControllName IsAllowed IsController
A Admin Home false false
A Home Null true true
这⾥约定分两个层次来判断权限:
第⼀条记录:表⽰A⾓⾊不能访问 Home/admin
第⼆条记录:表⽰A⾓⾊可以访问Controller下的所有⽅法
到底能不能访问呢?其实,我们以action为准,如果定义了action,我们直接从action的约定来判断,因此这⾥判断A不能访问Home/admin
其他⼏张表⼀看就明⽩,不再多说
判断是否有权限的设定
1、获取controller,action,以及存放在session中的⽤户信息
1 publicclass UserAuthorizeAttribute : AuthorizeAttribute
2 {
4 publicoverridevoid OnAuthorization(AuthorizationContext filterContext)
5 {
6 var user = filterContext.HttpContext.Session["CurrentUser"] as User;
7 var controller = filterContext.RouteData.Values["controller"].ToString();
8 var action = filterContext.RouteData.Values["action"].ToString();
9 var isAllowed =this.IsAllowed(user, controller, action);
10
11 if (!isAllowed)
12 {
13 filterContext.RequestContext.HttpContext.Response.Write("⽆权访问");
14 filterContext.RequestContext.HttpContext.Response.End();
15 }
16
17 }
18
19 ……
20
21 }
22
2、检索数据库ControllerAction表中有没有Name为第⼀步中controller 的记录,如果没有,我们约定这个controller是不需要进⾏权限控制的,如果有的话,进⼊第三步
3、前⾯提到了,我们约定对权限的控制分为两个层次,controller和action层次,如果同时定义了,以action为准。因此,我们需要判断是否在数据库中有action的记录,如果有,进⼊4,⽆,进⼊5
1 bool IsAllowed(User user, string controllerName, string actionName)
2 {
3 var service = ServiceLoader.LoadService<ToySpirit.IToySpiritService.IControllerActionService>();
4
5 // 获取对应的controller
6 var controller = service.GetSingleByExpression(c => c.Name == controllerName && c.IsController);
7 if (controller !=null)
8 {
9 // 获取对应的action
10 var
controllerAction = service.GetSingleByFunc(c => c.Name == actionName && c.IsController ==false&&c.ControllerName == controllerName);
11
12 return controllerAction ==null?this.isAllowed(user, controller) : this.isAllowed(user, controllerAction);
13 }
14
15 // 没有定义controller的权限,表⽰⽆需权限控制
16 returntrue;
17 }
18
19
4、如果有action的记录,那么我们⾸先判断controllerAction 拒绝哪些⾓⾊访问,如果⽤户有⾓⾊在这⾥⾯,很遗憾,就不能访问了;然后判断controllerAction 允许哪些⾓⾊访问,如果⽤户的⾓⾊在这⾥⾯,就可以访问了
注:这⾥很有可能⽤户有多个⾓⾊,⽐如A,B,C,如果A不能访问controllerAction,那么很遗憾,⽤户不能访问,尽管⾓⾊B,C可能可以访问该controllerAction
5、没有action的记录,⾃然就检查controller对应的controllerAction 了
4、5判断的代码是⼀样的,如下:
privatebool isAllowed(User user, ControllerAction controllerAction)
{
// 允许没有⾓⾊的:也就是说允许所有⼈,包括没有登录的⽤户
if (controllerAction.IsAllowedNoneRoles)
}
// 允许所有⾓⾊:只要有⾓⾊,就可以访问
if (controllerAction.IsAllowedAllRoles)
{
return user.Roles.Count >0;
}
if (user ==null|| user.Roles.Count ==0)
{
returnfalse;
}
// 选出action对应的⾓⾊
var roles = controllerAction.ControllerActionRoles.Select(ca => ca.Role).ToList();
if (roles.Count ==0)
{
// ⾓⾊数量为0,也就是说没有定义访问规则,默认允许访问
returntrue;
}
var userHavedRolesids = user.Roles.Select(r => r.ID).ToList();
/
/ 查禁⽌的⾓⾊
var notAllowedRoles = controllerAction.ControllerActionRoles.FindAll(r => r.IsAllowed ==false).Select(ca =>ca.Role).ToList(); if (notAllowedRoles.Count >0)
{
foreach (Role role in notAllowedRoles)
{
// ⽤户的⾓⾊在禁⽌访问列表中,不允许访问
if (userHavedRolesids.Contains(role.ID))
{
returnfalse;
}
}
}
// 查允许访问的⾓⾊列表
var allowRoles = controllerAction.ControllerActionRoles.FindAll(r => r.IsAllowed).Select(ca => ca.Role).ToList();
if (allowRoles.Count >0)
mvc的controller{
foreach (Role role in allowRoles)
{
// ⽤户的⾓⾊在访问的⾓⾊列表
if (userHavedRolesids.Contains(role.ID))
{
returntrue;
}
}
}
returnfalse;
}
使⽤⽅法:
建⽴⼀个basecontroller,使⽤我们定义好的UserAuthorize,然后所有的controller继承basecontroller就可以了
3 ///</summary>
4 [UserAuthorize]
5 publicabstractclass BaseController : Controller
6 {}
7
8 publicclass HomeController : BaseController{}
9
演⽰:
在controlleraction中添加⼏条数据:
根据我们的规则,我们可以知道,未登录的⽤户可以访问Home/Public,其他⼏个页⾯则不能访问我们看对应的Action:
1 publicvoid ViewPage()
2 {
3 Response.Write("View");
4 }
5 publicvoid Public()
6 {
7 Response.Write("Public");
8 }
9 publicvoid Delete()
10 {
11 Response.Write("Delete");
12 }
访问Home/Public,如果有权限,那么显⽰“Public“,否则显⽰”⽆权访问”
未登录⽤户访问Home/Public,结果符合我们的约定;-)
未登录⽤户访问Home/ViewPage,按约定应该显⽰错误信息
查看
原⽂出处
版权声明:本站内容均来自互联网,仅供演示用,请勿用于商业和其他非法用途。如果侵犯了您的权益请与我们联系QQ:729038198,我们将在24小时内删除。
发表评论