上一篇关于rbac的文章中,我简单介绍了实现rbac的理论思路。在本篇文章中,我将分析详细的将思考过程
1、数据库设计
在一个系统中,权限可以看做是原子操作,对于每一种角色,定义为权限集合,角色与权限的关系为多对多关系,用户与角色也是多对多的关系。从这个角度来看,我们实现权限管理系统,至少需要三个表,用户表,角色表和权限表。而用户与角色、角色与权限的关联关系的存储可以有多种实现方案。例如:可以在用户表里面添加一个字段,以点分字符串的形式存储当前这个用户拥有的角色列表,同理,角色表也可以添加一个字段,以点分字符串的形式存储当前角色拥有的操作权限。或者我们可以建立两个关系表,分别表示用户-角色关系和角色-权限关系。本例以点分字符串的形式来存储关联关系。所以只涉及到三个表:users/roles/resources。
2、原理设计
我们可以以手工的方式,将所有resources(api资源(url+method))先放到数据库中。然后只需要将特定的resource资源集合赋予给某角色就行了。然后以同样的方式将角色集合赋予给某用户就行。好了,赋予用户角色权限就没啥问题了。
假如用户A拥有了一定的权限,那么他登录之后,现在他对几个api接口发起了请求,系统中应该如何去判断该用户拥有哪些api的使用权限呢?
解决方案一:定义一个通用的服务方法,在每个接口里面判断当前用户有没有当前接口对应的角色。这个通用的服务方法可以implements InitializedBean ,从而实现其方法,达到对数据库的查询只做一次的目的,查询完一次之后,只需要将所有权限-角色集合的对应关系缓存起来,然后来一次请求,就从缓存中取出当前api所需的所有角色集合然后与当前用户拥有的角色集合取交集,如果交集大小为0,则表明当前用户没有权限,反之,则有。
解决方案二:可以将上述方案,移植到filter中。利用filter的init()方法只调用一次的特性,对数据库只查一次。而且,在filter中只需要将代码写一次就行了。是方案一的改进版本。