首页 诗词 字典 板报 句子 名言 友答 励志 学校 网站地图
当前位置: 首页 > 教程频道 > 软件管理 > 软件架构设计 >

小弟我设计的权限管理方案

2012-10-25 
我设计的权限管理方案这是给我们学校的某管理系统设计的一套权限管理子系统。今天把它总结一下,欢迎大牛过

我设计的权限管理方案

这是给我们学校的某管理系统设计的一套权限管理子系统。今天把它总结一下,欢迎大牛过来踩。

权限系统的设计对于企业级项目来说极为重要,尤其是像我们的系统,数据很重要,要是成绩被人修改了,那就糟糕了。

其实权限控制无非是两方面:控制合适的人访问到合适的菜单,进入合适的菜单项之后可以访问到合适的数据。

我把系统设计的尽量简化,主要牵涉到以下几个对象。

一个是权限所有者Accessor,即访问者

????? Accessor可以使一个用户,也可以是一个角色或是岗位,是什么只有客户程序知道。

?

一个是资源,Resource,表示可被访问的数据,

???? 为树形结构,每个资源为一个树的节点。客户程序可以自己控制资源的粒度。

?

一个是功能模块,Module,一个功能模块,或者是一个可访问的页面。

???? 由于这部分有其他人员开发,我的程序里面没有涉及到这个类,只是引用了这个类的ID。

?

一个是权限Authoritied,有三个外键,分别指向上面三个对象,其实就是一张三表关联的中间表。

?

针对以上所述,对程序敏感的你可能会提出以下问题:

1. Accessor可以是一个用户,也可以是一个角色或是岗位,那么如何表示一个访问者呢?

??? 我用了AccessorName这个字段,它是一个字符串类型,而且是不可重复的,由于我们的系统里表都有uuid,所以就把uuid放进来,作为AccessorName了。这里有一点,客户程序不只需用告诉我访问者的AccessorName是什么,并不需要知道这个Accessor是什么类型,所以这里的处理是可行的。

2. 这里的资源可以是各种类型,那么如何抽象的表示出各种类型的资源呢?

??? 这个问题和上面的类似,但处理方法不能一样,因为客户程序查询可访问资源列表之后需要知道资源的类型。处理的方法是,用Class类型的ResourceClass字段表示资源的类型,用ResourceId表示这个类型下的某个ID,通过这两个字段就可以确定资源是哪个具体的类型的实例了。

3. Authorited只是一张关联表,只能表示有没有访问的权限,不能表示权限的等级,比如读权限/写权限,那么如何控制权限等级呢?

???? 我是这么处理的,把菜单看做是一个功能模块,把菜单项看做是资源,而菜单细化到具体的功能,由于我们的系统里面每个页面的功能是相对单一的,没有把各种身份的功能做到一起,所以每一个菜单项就可以表示权限的等级了,比如查看成绩是一个菜单项,修改成绩是另外一个菜单项,这样只要控制这个人能否访问到指定页面就可以控制到权限等级。

?

?

以上是解决显示合适的菜单项的方案,当访问者进入合适的菜单项之后再查询可访问的资源列表,于是显示合适的数据。由于资源是树形结构,客户程序还可以查询某以某个资源实例为父资源的某种类型的资源,这样很容易控制数据的级联菜单形式的现实。

?

接下来就看一下我对外提供的操作接口方法是怎么样的吧。

?

public interface AclController {/** * 查询权限,返回的资源列表中的每一项都递归的包含父资源直到Root * @param accessor 访问者 * @param moduleId 访问的模块ID * @return 可访问的资源列表 * @throws AclDatabaseAccessException * @throws AclAnnotationConfigurationException * @author xuke */public List<Resource> get(Accessor accessor, Long moduleId) throws AclDatabaseAccessException, AclAnnotationConfigurationException;/** * 查询权限,返回的资源列表中的每一项都不包含父资源 * @param accessor 访问者 * @param moduleId 访问的模块ID * @param parent 父资源 * @param resourceClazz 父资源Class对象 * @return * @throws AclDatabaseAccessException * @throws AclAnnotationConfigurationException * @author xuke */public List<Resource> get(Accessor accessor, Long moduleId, Resource parent, Class resourceClazz) throws AclDatabaseAccessException, AclAnnotationConfigurationException;/** * 修改一个权限 * @param oldAuthoritied * @param newAuthoritied * @throws AclDatabaseAccessException * @throws AclAnnotationConfigurationException * @author xuke */public void modify(Authoritied oldAuthoritied, Authoritied newAuthoritied) throws AclDatabaseAccessException, AclAnnotationConfigurationException;/** * 获取根资源 * @return * @throws AclDatabaseAccessException * @throws AclAnnotationConfigurationException * @author xuke */public Resource getRootResource() throws AclDatabaseAccessException, AclAnnotationConfigurationException;/** * 增加一个资源 * @param resource * @throws AclDatabaseAccessException * @throws AclAnnotationConfigurationException * @author xuke */public void add(Resource resource) throws AclDatabaseAccessException, AclAnnotationConfigurationException;/** * 删除一个资源 * @param resource * @throws AclDatabaseAccessException * @throws AclAnnotationConfigurationException * @author xuke */public void delete(Resource resource) throws AclDatabaseAccessException, AclAnnotationConfigurationException;/** * 修改一个资源 * @param resource * @throws AclDatabaseAccessException * @throws AclAnnotationConfigurationException * @author xuke */public void modify(Resource resource) throws AclDatabaseAccessException, AclAnnotationConfigurationException;/** * 增加一个权限主体 * @param accessor * @throws AclDatabaseAccessException * @throws AclAnnotationConfigurationException * @author xuke */public void add(Accessor accessor) throws AclDatabaseAccessException, AclAnnotationConfigurationException;/** * 删除一个权限主体 * @param accessor * @throws AclDatabaseAccessException * @throws AclAnnotationConfigurationException * @author xuke */public void delete(Accessor accessor) throws AclDatabaseAccessException, AclAnnotationConfigurationException;/** * 修改一个权限主体 * @param accessor * @throws AclDatabaseAccessException * @throws AclAnnotationConfigurationException * @author xuke */public void modify(Accessor accessor) throws AclDatabaseAccessException, AclAnnotationConfigurationException;/** * 添加一个权限 * @param authoritied * @throws AclDatabaseAccessException * @throws AclAnnotationConfigurationException * @author xuke */public void add(Authoritied authoritied) throws AclDatabaseAccessException, AclAnnotationConfigurationException;/** * 删除一个资源 * @param authoritied * @throws AclDatabaseAccessException * @throws AclAnnotationConfigurationException * @author xuke */public void delete(Authoritied authoritied) throws AclDatabaseAccessException, AclAnnotationConfigurationException;}

?其实权限系统主要是设计,至于如何实现都是小事情,简单说一下把,我的这个模块里是用spring做ioc的,数据库操作方面考虑到效率问题所以是用的jdbc,但模仿了hibernate的Annotation的配置方式,自己实现了表和字段的映射,所以sql是自动生成的,如果数据库改了,sql是不需要改的。

有兴趣的可以看看我的整个的代码,欢迎大牛给出宝贵意见,小弟先受了。

?

1 楼 metadmin 2009-06-15   我是一直搞权限管理的,搞了4年多。欢迎试用我们的细粒度权限管理产品 www.metadmin.com。 有90天试用期。


也不敢说是大牛,就谈谈自己的看法吧。
1,从功能角度来看,如你所说,权限管理分为2种层次,a,功能控制;b,功能里面的资源控制。
2,从管理角度来看,分为2个方面。a, 最终用户需要管理的权限(比如分配角色、管理角色权限呀);b, 开发者需要管理的地方,开发者根据需求把客户提出的细粒度控制实现了。可以是硬coding,也可以是配置。

但不管采取那种手段,不要改变客户需要控制的部分。毕竟角色、用户、权限这种RBAC模型深入人心了。


权限控制可以分为2类:
1,查询数据的控制,这个IBM/ORACLE查询没有做,metadmin做了控制。查出当前用户具有权限查看的数据,而且要支持分页、自定义条件;
2,数据控制类,这个IBM/ORACLE有做,metadmin也做了。也就是判断当前用户对某条数据是否有操作权限,返回true/false。


我们产品现在做到,权限逻辑全部提取出来,而且不需要编码和xml配置,通过界面就能把权限配置出来,还可以在线测试。 有兴趣欢迎浏览 www.metadmin.com 有试用版,还有demo演示

热点排行