本文我们将讨论的是ASP.NET MVC Membership权限的设置,以及其他的一些问题。希望能帮助大家更好的应用ASP.NET MVC,令开发更快乐。
以前一位同事习惯于使用Membership来进行权限管理,现在随着ASP.NET MVC的引入,采用以前的方法,提出了以下方案:
ASP.NET MVC+Membership结合,通过在web.config中进行配置,来管理系统中的权限。
于是,我对这个方案的可行性进行了分析,提出了以下疑点:
在ASP.NET 2.0的Membership中, 在Web.config中是通过物理文件和目录,那么在ASP.NET MVC中,如果在URL中直接输入物理文件和目录,是找不到这个文件的,不知道这种方式还能不能奏效。如果说不管在mvc中,通过URL Routing怎么绕,最终都会定位到物理文件和目录上,这种方式是行得通的。如果不是文件目录结构的话,web.config这种配置是否还能用?关于我提出的这个疑点,当时我觉得非常的有趣。为了验证我的疑点,于是我做了一个测试。
经过一个简单的Demo,测试结果出来了。测试结果如下:
在ASP.NET MVC的Membership中,并不是基于文件和目录的,而是易于URLRouting的,当进行文件目录配置的话,是不起作用的,只有在web.config中进行URLRouting的权限配置才会起作用。最终经过测试,如果按照默认路由走的话,最终也是可以通过配置进行权限的控制。只不过是配置起来的话,要把文件路径改为“controller/action”而不是原来的“Controller/Action.aspx”。
接下来再想一想,这样会不会有什么问题?
以往的Webform开发,url是稳定因素(URL重写除外),所以,通过Membership进行权限设定是没有问题的。但是在MVC中,URL是不稳定因素,如果更改了routing设置,权限系统就会被绕过去。从模块职责上来说,不应该因为其它模块的更改,导致权限管理模块失效,这从设计上就是一个糟糕的设计。所以,从个人情感上来说,我认为这种设计糟糕透了。既然URL是不稳定因素,不应该通过这个来进行权限控制,也就是说不应该通过不稳定因素来参杂权限管理。 URL是不稳定的,那么较稳定的因素应该就是Controller跟Action,也就是说,无论URL怎么变,最终都可以把Controller跟Action确定下来。因此,在ASP.NET MVC中,应该通过Controller跟Action结合来进行权限控制。了解URLRouting的朋友们一定知道,MVC中的路由是按照顺序执行的,如果满足了前面的匹配规则,将不会执行后面的匹配规则,稍稍对于URLRouting掌握不好,就会给系统的安全带来隐患。
权限系统一般分为:稳定不变的部分、较稳定的部分、不稳定部分。因此在进行权限系统的时候就应当综合考虑这些因素。
关于权限系统的设计,一般都会按照如下来设计:
抽象出系统中的实体部分(系统中稳定不变的部分或系统中较稳定的部分)。 将抽象的实体部分进行抽象设计(实体类)。设计实体类之间的存储。
分析实体类之间的关系,这些是系统中不稳定的部分,因此要将这些关系进行存储(存储在数据库中或配置文件中,方便以后进行修改)。经过如上的设计,一般来说当权限管理系统达到如下要求就算是合格了:
能完成基本的权限管理当需要进行权限管理的时候,整个权限系统的架构不变,变的仅仅是数据。一个合格的权限系统的设计通常不够完美,所以需要结合实际情况综合考虑进行改进。至于如何改进,没有统一的方法可言。
关于Membership,很多人都喜欢重用Membership的一些东西,可是究竟能够重用的部分有多少?
ASP.NET 2.0中提供的控件,如: Login、LoginView、PasswordRecovery、CreateUserWizard、ChangePassword等,当然,这些并不是Membership的部分,但是这些通常都会跟Membership配合使用。这些控件提供了方便的开发,可是通常这些控件并不能满足要求,扩展性并不好,而且这些控件会生成很多垃圾代码如:js、css等。在带来开发方便的同时,也给扩展跟维护带来不便。最重要的一点,凡是涉及Postback的控件,在ASP.NET MVC中,全部不能使用。
数据库及数据库访问。通过执行“aspnet_regsql”命令,可以自动在数据库中创建出11张表,并且提供了若干个API方法来对这11张表进行操作。可是这11张表中的设计往往也是不符合要求的,如果进行扩展的话,就会比较麻烦。一般扩展的方法有两种:不改变原来的表,但是要建一张表跟以前的表对应,表中的Id跟原来表中一模一样;改变原来表的设计。无论是哪种方法,数据库访问部分就必须得重写,因此数据库及数据库访问的重用也变的非常低。基于配置文件的权限控制,似乎从目前上来看,能重用的部分只有这个了。可是在ASP.NET MVC中URL是个不稳定因素,基于配置文件的权限控制这个功能的重用并不适合ASP.NET MVC的开发。综合对比一下,至少在ASP.NET MVC开发中,Membership所带来的重用微乎其微。
在不同的权限管理系统中,对控制级别的要求是不一样的,如:页面访问级别、数据访问级别、控件访问级别、函数级别。。。。。。可是不论是要控制到那个级别,权限管理系统所要完成的功能都是一样的 。我们不妨给权限管理系统下一个定义:权限管理系统就是告诉其它模块用户/角色对特定的资源/功能是否具有访问的权限。
在Webform中,用户跟角色相比,角色是不稳定因素,用户是相对较稳定的因素。因此权限系统的输入参数中我们通常会传入用户,而不输入角色,因为角色是不稳定的,至于说用户属于哪个角色,权限系统是可以查出来的。
而在ASP.NET MVC中,用户跟角色都可以是较稳定因素,因为用户的权限控制跟角色的权限控制都是通过扩展标记属性来实现的。这是跟webform相比,权限系统设计上不一样的地方。
ASP.NET MVC中权限控制是通过对Action的拦截实现的。实现的方式如下:
定义一个扩展属性标记类,继承自接口IActionFilter的抽象类ActionFilterAttribute。重写ActionFilterAttribute中的虚方法。将扩展标记作用于Controller跟Action。关于ASP.NET MVC中的权限管理方案,网上已经有了,这里就不过多的赘述了。