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

1 publicclass UserAuthorizeAttribute : AuthorizeAttribute 
 2     {
 3 
 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) 
            { 
                returntrue; 
            } 
            // 允许所有角色:只要有角色,就可以访问 
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) 
            { 
                foreach (Role role in allowRoles) 
                { 
                    // 用户的角色在访问的角色列表 
if (userHavedRolesids.Contains(role.ID)) 
                    { 
                        returntrue; 
                    } 
                } 
            } 
            returnfalse; 
        }

使用方法:

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

1 ///<summary> 
2 /// 控制基类 
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,按约定应该显示错误信息

本文参与腾讯云自媒体分享计划,欢迎正在阅读的你也加入,一起分享。

发表于

我来说两句

0 条评论
登录 后参与评论

相关文章

来自专栏分布式系统和大数据处理

HttpModule介绍

Http 请求处理流程 和 Http Handler 介绍 这两篇文章里,我们首先了解了Http请求在服务器端的处理流程,随后我们知道Http请求最终会由实现了...

793
来自专栏Create Sun

quartz.net任务调度:源码及使用文档

前言   前段时间把自己封装quartz.net 类库的过程总结到博客园,有网友想要看一下源码,所以就把源码传到github上去了,今天把地址分享给大家,程序中...

3919
来自专栏.NET开发那点事

使用Microsoft Fakes进行单元测试(1)

一:什么是单元测试 单元测试是对软件进行准确性验证的步骤。单元测试并不进行整个软件功能的测试,仅仅是对于最小工作单元的测试。一般最小工作单元就是指方法/函数等...

2426
来自专栏Pythonista

Django之Form功能

Django表单系统中,所有的表单类都作为django.forms.Form的子类创建,包括ModelForm

1972
来自专栏技术博客

Asp.Net MVC3.0网站统计登录认证的在线人数

  对于一个网站来说,统计在线人数是一个很重要的工作。平时也发现很多的网站论坛等都有在线人数的显示。对于一个网站如果在线人数很多,用户看到了这么个数字也是很了不...

1422
来自专栏码农阿宇

.Net Core从命令行读取配置文件

最近在学习博客园腾飞(jesse)的.Net Core视频教程,收益匪浅,在此作推荐 : http://video.jessetalk.cn/ 言归正传,.Ne...

3094
来自专栏听雨堂

页面状态保持机制(编辑中)

Web应用程序中,有很多状态需要在页面的反复回调中能够保持住,还有一些状态需要在页面之间保持。对于状态的保持,是一个值得研究的问题。状态处理不当是页面失效或错误...

2835
来自专栏崔庆才的专栏

妈妈再也不用担心爬虫被封号了!手把手教你搭建Cookies池

6434
来自专栏hbbliyong

WCF浅尝

1.首先先建立一个WCF服务应用程序 ? 2.再建立一个宿主程序,这里用控制台,添加服务引用,这里会报错: ? 点击页面确定,回到添加服务页面 ? 点击箭头有如...

36110
来自专栏智能合约

node.js实现CURL功能

3012

扫码关注云+社区

领取腾讯云代金券