分类:
2006-09-08 00:07:13
习惯地,对权限控制的定义为: 控制实体访问指定资源的权限
在WEB开发中,实体一般指用户/角色/组,资源则指URL(泛化为ACTION,MODULE等),以下的权限控制方法,只是一种在脑内存在多时的想法,并无真正实现代码,仅供参考:
一、 实体及其关系
本文采用的实体为用户和角色,关系为多对多,即一个用户可属于多种角色,一个角色可有多个用户
[user] //用户表
-------------------------------
id
name
.
.
state
说明:用户表沿用常规的应用程序用户表结构,如需要,可增加类型为ENUM的state字段,表明用户是否正常使用,如果state为0,则禁止登陆系统
[role]//角色表
---------------------------------
id
name
state
说明:name为角色名称,state同user表,值为0时,表示被禁止,属于该角色的权限也失效
[user_role] //用户与角色的关系(多对多)
-----------------------------------
id
user_id
role_id
这样,要获得某用户所充当的所有角色,只需执行
SELECT role_id FROM user_role WHERE user_id = xxx |
如果只要获得有效的角色,则加上state = 1的条件.
同样地,要获得某角色的所有用户,查语句为:
SELECT user_id FROM user_role WHERE role_id = xxx |
补充说明:同样地,也可以采用单一角色设计,即一个用户只可以充当一种角色,一个角色可有多个用户,这时,无需用户_角色关系表,只需在用户表中加入role_id字段,标识该用户所有的角色即可.
二、 资源、ACL
WEB的资源,一般就是指URL,在MVC等分层的结构中,也可以指ACTION,MODULE等模块化的标识.
[resource] //资源表
-------------------------------------------
id
name 资源名称(用于显示)
flag 资源标识(用于判断)
state ENUM(‘normal’,’disabled’,’nocheck’)
//资源状态,优先级高于acl表,如状态为nocheck,则无需检查acl,任何人均有权,为disabled表示资源被停用,任何人不可访问
[resource_acl] //资源存取表
--------------------------------------------
id
resource_id 资源id
entity_id 实体id,即user_id或role_id
entity_type 实体类形,ENUM(‘user’,’role’);
allow_ip 允许访问的ip,为空表示不限ip
allow_time 允许访问的时间,为空表示不限
说明:
1) 这里只实现简单的ip控制,更复杂的可单独设一个acl_ip的表,再细分允许和禁止ip
2) allow_time采用与linux corn相类似的格式,但只取时间,星期,日三个字段,以空格分隔
时间:用24小时制,可包括分,用:分隔
星期:0-6,星期天用0表示
日:1-31
对于每一字段,用*表示任意(即不限),中划线-表示范围,逗号,表示只选列出,例
9-17:30 1-5 * 表示每星期一至五的9点至17:30有权
* 1,3,5 * 表示逢星期一,三,五有权
16 * 10 表示每月10号的16点有权
三、 权限定义及读取
表设计好后,设定好用户,角色及其关系,然后把全部资源加入到资源表,再对实体赋予一定的权限(也可对指定的资源分配可访问的实体),方法是:对每个实体可访问的每一资源加入一条记录至resource_acl,如id为12的用户对资源1,和3有权,则结果类似
id | resource_id | entity_id | entity_type | allow_ip | allow_time |
1 | 1 | 12 | user | ||
2 | 3 | 12 | user |
另外:如果只对少量的资源限制(即不限制的比限制的多),可采用未加入资源表的为有权的方式,即在资源表中搜索不到该资源时,直接返回有权,无需用resource_acl判断
应用权限:
权限定义后,具体的控制处理流程是:
1) 用户登陆 –> 获得用户id及用户所有有效的角色id -> 在resource_acl中查找所有该用户及其所属角色的记录 -> 如果需要,分析ip和时间,去除不通过的记录 -> 最终结果以数组方式存入session,tmpfs或memcache等
2) 用户访问指定资源 -> 如果有定义,判断当前资源是否无需验证(状态为nocheck或不在资源表中),如果是,直接返回有权 –> 从session或memcache等中取出当前用户的权限列表,比较当前请求的资源是否在列表中来确定是否有权访问.