一、概述
1.系统权限控制功能分为两种:URL请求权限校验和页面渲染权限校验;两种场景使用作用不同,但依赖的规则是相同的。
2.权限在实现时,需要做到支持不同店铺可以对店内成员账号进行权限分配,也就是说:权限的个性化;第一版实现统一定制的权限配置,第二版实现个性化可配置;本次设计支持可配置的需求,开发时根据需要进行实现。
二、数据库设计
分析一下几个业务实体概念:
用户:每个店铺在BC-SHOP系统中开通服务后,都需要生成一个管理员账号,管理员账号可以在系统中创建普通账号,这些账号都作为“用户”存在;
用户组:用户组是将系统中的所有用户按照职责和权限级别的差异进行分组,也就是说,属于不同用户组用户各自享有不同的权限,这些权限是通过配置映射到用户组;第一版实现时先对用户组预定义,所有店铺都使用系统预定好的几个用户组;
角色:某种角色在系统中被赋予一批读写权限,若干个角色被添加给某个用户组后,这个用户组就享有这些角色所拥有权限的并集;
权限资源:将系统中所有最小粒度的操作(读、写)权限项定义为权限资源,当资源被赋给角色时,角色就拥有了系统操作的某项权限;资源分为若干种:请求url、页面元素、页面等;
模块:权限资源在配置时,用户需要参考该权限资源属于哪个模块;例如:“入库单保存功能”资源属于“进销存”模块;
总之:我们在进行权限校验是,根据当前登录的用户账号得知该用户是属于哪个用户组,根据用户组获得该用户组拥有的所有角色,获得所有被赋给这些角色的权限资源列表,匹配当前被请求的权限资源是否在这个列表中,即可达到权限校验的目的。
注:本次设计并未实现对资源读写权限的区分,该设计需要根据后续用户需求考虑是否在现有设计基础上进行扩展。
根据概念模型,对物理模型设计如下:
三、程序设计
由于权限相关的数据在用户的每一次请求中都会被调用,因此数据的读效率非常关键,分析权限数据特点如下:
1.读取频率非常高
2.修改频率比较低
3.权限相关数据量可能出现海量数据,并且保持稳定;但是,其中用户信息会随着店铺数量的增加而增加,在可预见的业务范围内,有可能达到百万数量级;
因此将权限数据存放在内存中是必要的,除用户数据外,其余数据适合放在应用服务器本地内存中,用户数据放在memcached服务器内存中;下图为对权限相关数据缓存机制的设计:
类的职责说明:
MemCacheAdapter?:memcached缓存适配器,所有需要对memcached中的数据执行读、写操作的逻辑都需要调用这个类中的方法;
LocalCacheManager?:管理本地缓存数据的读写;使用Hashtable数据结构封装存储在本地JVM中的数据,Role、Resource、UserGroup?、Module存储在LocalCacheManager中,该类中提供了对各种缓存数据的读写操作方法;业务Service类第一次从数据库中读取缓存尚不存在的数据后,添加到LocalCacheManager中对应的Hashtable,之后所有读取操作都可以直接从内存中获得;另外,LocalCacheManager中对每一个数据都有timeout,每一次时间阀经过之后,最近的下一次读操作需要从memcache中获取是否有更新的标记,通过这种方式,达到本地内存与数据库中的数据保持同步(存在较少的延迟);
UserService?:用户数据读写操作服务类;
UserGroupService?:用户组读写操作服务类;
RoleService?:角色读写操作服务类;
ResourceService?:权限资源读写操作服务类;
Module:功能模块读写操作服务类;
应用逻辑通过从缓存中取数据,再进行校验,对于URL请求和页面渲染两种场景,设计两种实现,并抽取两者公共逻辑:
请求权限控制调用过程如下:
页面渲染权限控制调用过程如下: