我设计的权限管理方案

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

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

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

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

一个是权限所有者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是不需要改的。

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

 

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值