asp.net MVC 权限设计

几点说明:

 

    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中的用户信息

public class UserAuthorizeAttribute : AuthorizeAttribute 
    {

     public override void OnAuthorization(AuthorizationContext filterContext) 
      { 
          var user = filterContext.HttpContext.Session["CurrentUser"] as User; 
          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(); 
          } 

      }

    ……

}

2、检索数据库ControllerAction表中有没有Name为第一步中controller 的记录,如果没有,我们约定这个controller是不需要进行权限控制的,如果有的话,进入第三步

 

   3、前面提到了,我们约定对权限的控制分为两个层次,controller和action层次,如果同时定义了,以action为准。因此,我们需要判断是否在数据库中有action的记录,如果有,进入4,无,进入5

bool IsAllowed(User user, string controllerName, string actionName) 
{ 
    var service = ServiceLoader.LoadService<ToySpirit.IToySpiritService.IControllerActionService>(); 

    // 获取对应的controller 
     var controller = service.GetSingleByExpression(c => c.Name == controllerName && c.IsController); 
    if (controller != null) 
    { 
        // 获取对应的action 
         var controllerAction = service.GetSingleByFunc(c => c.Name == actionName && c.IsController == false && c.ControllerName == controllerName); 

        return controllerAction == null ? this.isAllowed(user, controller) : this.isAllowed(user, controllerAction); 
    } 

    // 没有定义controller的权限,表示无需权限控制 
     return true; 
}

4、如果有action的记录,那么我们首先判断controllerAction 拒绝哪些角色访问,如果用户有角色在这里面,很遗憾,就不能访问了;然后判断controllerAction 允许哪些角色访问,如果用户的角色在这里面,就可以访问了

注:这里很有可能用户有多个角色,比如A,B,C,如果A不能访问controllerAction,那么很遗憾,用户不能访问,尽管角色B,C可能可以访问该controllerAction

5、没有action的记录,自然就检查controller对应的controllerAction 了

代码

4、5判断的代码是一样的,如下:

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

            // 允许所有角色:只要有角色,就可以访问 
            if (controllerAction.IsAllowedAllRoles) 
            { 
                return user.Roles.Count > 0; 
            } 

            if (user == null || user.Roles.Count == 0) 
            { 
                return false; 
            } 

            // 选出action对应的角色 
            var roles = controllerAction.ControllerActionRoles.Select(ca => ca.Role).ToList(); 
            if (roles.Count == 0) 
            { 
                // 角色数量为0,也就是说没有定义访问规则,默认允许访问 
                return true; 
            } 

            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)) 
                    { 
                        return false; 
                    } 
                } 
            } 

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

            return false; 
        }


使用方法:

 

建立一个basecontroller,使用我们定义好的UserAuthorize,然后所有的controller继承basecontroller就可以了

/// <summary> 
   /// 控制基类 
   /// </summary> 
    [UserAuthorize] 
   public abstract class BaseController : Controller 
   {}

   public class HomeController : BaseController{}

示:

 

在controlleraction中添加几条数据:


根据我们的规则,我们可以知道,未登录的用户可以访问Home/Public,其他几个页面则不能访问

我们看对应的Action:

public void ViewPage() 
       { 
           Response.Write("View"); 
       } 
       public void Public() 
       { 
           Response.Write("Public"); 
       } 
       public void Delete() 
       { 
           Response.Write("Delete"); 
       }

访问Home/Public,如果有权限,那么显示“Public“,否则显示”无权访问”

未登录用户访问Home/Public,结果符合我们的约定;-)



评论 3
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值