一、基本配置
注:我这里与ThinkPHP官网提供的源码有些区别,将
RBAC_NODE_TABLE改为了RBAC_POWER_TABLE,并且里面的数据库和字段名字也有些区别,所以要先将相关的变量、数据库和字段的名字该过来。(在VIM中可以用
:12,23s/
RBAC_NODE_TABLE/
RBAC_POWER_TABLE/g 将从12行到23行中出现的所有包含
RBAC_NODE_TABLE的字符串中的
RBAC_NODE_TABLE替换为
RBAC_POWER_TABLE)。
1、第 7 行:配置了认证SESSION标记为authId,这个值随便配置,只要不系统中现有的$_SESSION 不冲突便可(例如:$_SESSION[‘USER_AUTH_KEY’] 相当于$_SESSION[‘authId’])
2、第 11 行:‘USER_AUTH_GATEWAY’=>’/Public/login’ // 也就是用户登录后台的一道门,若已经登录,则会直接跳转到后台主页面;相反,没有设置$_SESSION[‘authId’]这个值,或者已经过期,将会显示登录页面;
3、PublicAction.class.php
checkUser
检查用户是否登录
top
footer
menu
main
login
index
logout
checkLogin
changePwd
profile
verify
change
IndexAction.class.php
二、RBAC类中的 方法
1、authenticate($map,$model='') //1.认证方法 2.使用给定的Map进行认证 3.传入查询用户的条件和用户表的MODEL 返回数组包含用户的信息
// 认证方法
2、saveAccessList($authId=null)//1.用于检测用户权限的方法,并保存到Session中
传入用户的ID 2.此方法不返回值,只是设置 $_SESSION['_ACCESS_LIST']的值,其中包含了所有该用户对应的用户组的有权限操作的所有节点$_SESSION['_ACCESS_LIST']['项目名']['模块名']['操作名'],以后判断权限就是判断当前项目,模块和操作是否在 $_SESSION['_ACCESS_LIST']中能找到。
saveAccessList方法在Lib\ORG目录下RBAC.class.php文件里,登陆时checkLogin方法有导入这个文件。
static function saveAccessList($authId=null)
3、getRecordAccessList()// 取得模块的所属记录访问权限列表 返回有权限的记录ID数组
104
if(null===$authId)
$authId = $_SESSION[C('USER_AUTH_KEY')];
105
if(empty($module))
$module =
MODULE_NAME;
106
//获取权限访问列表
107
$accessList = RBAC::getModuleAccessList($authId,$module);
108
return $accessList;
109
}
4、checkAccess() 方法 检测当前模块和操作是否需要验证 返回bool类型
static function checkAccess()
113
{
114
//如果项目要求认证,并且当前模块需要认证,则进行权限认证
115
if( C('USER_AUTH_ON') ){
116
$_module
=
array();
117
$_action
=
array();
118
if("" != C('REQUIRE_AUTH_MODULE')) {
119
//需要认证的模块
120
$_module['yes'] = explode(',',strtoupper(C('REQUIRE_AUTH_MODULE')));
121
}else {
122
//无需认证的模块
123
$_module['no'] = explode(',',strtoupper(C('NOT_AUTH_MODULE')));
124
}
125
//检查当前模块是否需要认证
126
if((!empty($_module['no']) && !in_array(strtoupper(MODULE_NAME),$_module['no'])) || (!empty($_module['yes']) &&
in_array(strtoupper(MODULE_NAME),$_module['yes']))) {
127
if("" != C('REQUIRE_AUTH_ACTION')) {
128
//需要认证的操作
129
$_action['yes'] = explode(',',strtoupper(C('REQUIRE_AUTH_ACTION')));
130
}else {
131
//无需认证的操作
132
$_action['no'] = explode(',',strtoupper(C('NOT_AUTH_ACTION')));
133
}
134
//检查当前操作是否需要认证
135
if((!empty($_action['no']) && !in_array(strtoupper(ACTION_NAME),$_action['no'])) || (!empty($_action['yes']) &&
in_array(strtoupper(ACTION_NAME),$_action['yes']))) {
136
return true;
137
}else {
138
return false;
139
}
140
}else {
141
return false;
142
}
143
}
144
return false;
145
}
5、checkLogin()方法 检测登录
149
//检查当前操作是否需要认证
150
if(RBAC::checkAccess()) {
151
//检查认证识别号
152
if(!$_SESSION[C('USER_AUTH_KEY')]) {
153
if(C('GUEST_AUTH_ON')) {
154
// 开启游客授权访问
155
if(!isset($_SESSION['_ACCESS_LIST']))
156
// 保存游客权限
157
RBAC::saveAccessList(C('GUEST_AUTH_ID'));
158
}else{
159
// 禁止游客访问跳转到认证网关
160
redirect(PHP_FILE.C('USER_AUTH_GATEWAY'));
161
}
162
}
163
}
164
return true;
165
}
6、AccessDecision($appName=APP_NAME) 方法 就是检测当前项目模块操作是否在$_SESSION['_ACCESS_LIST']数组中,也就是说 在 $_SESSION['_ACCESS_LIST'] 数组中$_SESSION['_ACCESS_LIST']['当前操作']['当前模块']['当前操作']是否存在。如果存在表示有权限否则返回flase。
168
static public function AccessDecision($appName=APP_NAME)
169
{
170
//检查是否需要认证
171
if(RBAC::checkAccess()) {
172
//存在认证识别号,则进行进一步的访问决策
173
$accessGuid
=
md5($appName.MODULE_NAME.ACTION_NAME);
174
if(empty($_SESSION[C('ADMIN_AUTH_KEY')])) {
175
if(C('USER_AUTH_TYPE')==2) {
176
//加强验证和即时验证模式 更加安全 后台权限修改可以即时生效
177
//通过数据库进行访问检查
178
$accessList = RBAC::getAccessList($_SESSION[C('USER_AUTH_KEY')]);
179
}else {
180
// 如果是管理员或者当前操作已经认证过,无需再次认证
181
if( $_SESSION[$accessGuid]) {
182
return true;
183
}
184
//登录验证模式,比较登录后保存的权限访问列表
185
$accessList = $_SESSION['_ACCESS_LIST'];
186
}
187
//判断是否为组件化模式,如果是,验证其全模块名
188
$module = defined('P_MODULE_NAME')?
P_MODULE_NAME
:
MODULE_NAME;
189
if(!isset($accessList[strtoupper($appName)][strtoupper($module)][strtoupper(ACTION_NAME)])) {
190
$_SESSION[$accessGuid]
=
false;
191
return false;
192
}
193
else {
194
$_SESSION[$accessGuid]
=
true;
195
}
196
}else{
197
//管理员无需认证
198
return true;
199
}
200
}
201
return true;
202
}
7、getAccessList($authId) 方法 通过查询数据库 返回权限列表 $_SESSION['_ACCESS_LIST']的值,取得当前认证号的所有权限列表。
View Code
static public function getModuleAccessList($authId,$module) {
283 // Db方式
284 $db = Db::getInstance(C('RBAC_DB_DSN'));
285 $table = array('role'=>C('RBAC_ROLE_TABLE'),'user'=>C('RBAC_USER_TABLE'),'access'=>C('RBAC_ACCESS_TABLE'));
286 $sql = "select access.power_id from ".
287 $table['role']." as role,".
288 $table['user']." as user,".
289 $table['access']." as access ".
290 "where user.user_id='{$authId}' and user.role_id=role.id and ( access.role_id=role.id or (access.role_id=role. role_pid and role.role_pid!=0 ) ) and role.status=1 and access.power_module='{$module}' and access.status=1";
291 $rs = $db->query($sql);
292 $access = array();
293 foreach ($rs as $power){
294 $access[] = $power['power_id'];
295 }
296 return $access;
297 }
RBAC的委托认证方法
authenticate($map,$model='User',$provider=USER_AUTH_PROVIDER)
代码方法是静态方法,支持三个参数,其中第一个认证条 件$map是必须的,可以灵活地控制需要认证的字段。第二个参数是进行认证的模型类,默认是UserModel类 第三个参数是委托方式 由 USER_AUTH_PROVIDER 设置委托认证管理器的委托方式,目前支持的是 DaoAuthentictionProvider
通过数据库进行认证。在应用系统的开发过程中,只需要设置相关的配置项和添加上面的认证方法,其他的认证和决策访问就由RBAC组件的AccessDecision方法自动完成了。系统会在执行某个模块的操作时候,首先判断该模块是否需要认证,如果需要认证并且已经登录,就会获取当前用户的权限列表判断是否具有当前模块的当前操作权限,并进行相应的提示。接下来就是在框架总后台设置相关项目的模块 和操作权限了。 关于如何授权请参考示例中心提供的RBAC示例
首先,在节点管理添加相关项目、模块和操作,作为权限管理的节点。
如果需要设置公共的操作,可以使用Public模块,所有属于Public模块的操作对所有模块都有效。
添加完成项目管理节点后,就在权限管理里面对某个用户组设置相关权限(包括项目权限、模块权限和操作权限)
以后需要授权就把用户添加到某个权限组就可以了,同一个用户可以属于多个权限组。
授权和认证功能涉及到四个数据表,DB_PREFIX为配置文件中设置的数据库前缀
DB_PREFIX_group 权限组表
DB_PREFIX_groupuser 组-用户关联表
DB_PREFIX_access 访问权限表
DB_PREFIX_node 权限节点表
所谓的授权操作其实就是往DB_PREFIX_groupuser表和DB_PREFIX_access里面写入数据
至于数据表的字段官方给出的示例仅供参考,可以通过修改ORG.RBAC.AccessDecisionManager 类来完成项目的需要。