|
马上注册,结交更多好友,享用更多功能,让你轻松玩转社区。
您需要 登录 才可以下载或查看,没有帐号?立即注册
x
到现在,对排版还是不很熟练,经常会排不好。会见|开辟指南|掌握 若何利用 RBAC 组件?
请务必更新到 1.0.60.553 版本以上,确保 RBAC 组件与文档中的描写符合合
RBAC 是英文(Role-Based Access Control)的缩写,也就是基于脚色的会见掌握。RBAC 的界说对照流畅,我就以对照活泼的模式来论述甚么是 RBAC。
ATM 机的一天
假定有一台 ATM(主动提款机)放在街边,咱们来看看这个 ATM 渡过的一天。
- 早上,有一个家伙走到 ATM 眼前,对着机械说:“芝麻开门,芝麻开门,给我 100 块!”。很明显 ATM 不会有任何举措。绝望之余,这个家伙踢了 ATM 一脚走了。
- 午时,一名大度的 Office lady 走到 ATM 机眼前,放入她的信誉卡,输出暗码后,掏出了 1200 块钱。固然,这些钱很快就会酿成一件衣服或是化装品。
- 上班时分,银行的任务人员离开 ATM 机械眼前,放入一张特制的磁卡,然后输出暗码。从中查询到 ATM 机械内还有充分的现金,无需增补。所以他很乐意的开着车去下一台 ATM 机械地点地了。
如今咱们要开辟一台具有一样功效的 ATM 机,应当怎样做呢?
起首,咱们的 ATM 机不克不及让人随意取钱,否则银行会破产的。接上去,ATM 机需求一个让人们放入磁卡并输出暗码的装备。人们放入磁卡并输出暗码后,ATM 机还要可以判别这张磁卡的卡号和暗码是不是无效,而且婚配。以后,ATM 机必需判别磁卡的卡号属于哪一种类型,假如是信誉卡,那末则显示查询账户余额和取款的界面。假如是特制的磁卡,则显示 ATM 机内的现金余额。
ATM 与 RBAC
下面的例子显得有点怪诞,然而倒是一个典范的基于脚色的会见掌握。
- 关于没有磁卡或输出了毛病暗码的用户,一概回绝办事,也就是不答应停止任何其他操作;
- 假如输出了准确的暗码,必需判别用户输出哪种类型,并供应响应的办事界面;
- 假如用户测验考试会见本人不克不及利用的办事,那末要明白告知用户这是不成能的。
这个流程中,一共呈现了两种脚色:信誉卡用户和办理卡用户。而那些没有磁卡的用户,都属于没有脚色一类。RBAC 要可以任务,最少需求两个数据:脚色信息和会见掌握表。
脚色信息凡是是指某个用户具有的脚色,例如你持有一张信誉卡,那末你就具有“信誉卡用户”这个脚色。假如你持有一张办理卡,那末你就具有“办理卡用户”这个脚色。假如你既没有信誉卡,又没有办理卡,那末你就没有上述两种脚色。
有了脚色信息,RBAC 体系还需求一个会见掌握表。会见掌握表(Access Control Table)是一组数据,用于指出哪些脚色可使用哪一个功效,哪些脚色不克不及利用哪一个功效。例如在 ATM 机中,具有“信誉卡用户”脚色,就能够利用查询账户余额和取款两项功效;而具有“办理卡用户”脚色,就能够利用查询 ATM 机内现金余额的动能。
咱们来摹拟一次 ATM 机的操作:
- 唐雷有一张信誉卡,他放入 ATM 机并输出了准确的暗码。这时候,他被 ATM 机以为具有“信誉卡用户”脚色。
- 依据下面的判别了局,ATM 机显示了一个操作界面,下面有查询账户余额和取款两项操作按钮。
- 唐雷按下了“查询账户余额”按钮,ATM 机的查询账户余额功效被挪用。
- 在查询账户余额功效中,再次反省用户的脚色信息,肯定他可使用这个功效。
- 停止一系列操作,然后将唐雷信誉卡账户上的余额数字显示到屏幕上。
- 唐雷很愁闷他的信誉卡又透支了,悻悻然掏出卡走人了。这时候 ATM 主动排除以后的脚色信息,为下一次操作做好筹办。
从下面可以看出,RBAC 充任了体系的一道平安樊篱。一切的操作都需求进过 RBAC 验证事后才干利用。如许充实包管了体系的平安性。
RBAC 概念
在 FleaPHP 的 RBAC 组件中,只要以下几项概念需求了解:
- 用户:使用法式的利用者;
- 脚色:一个名字,可觉得用户指定多个脚色(0-n);
- 会见掌握表(ACT):一个数组,用来指明哪些功效可以被哪些脚色会见或限制会见。
除上述三个概念,要想 RBAC 体系可以正常任务,还需求用户信息办理器、脚色信息办理器和会见掌握器三个部件。
- 用户信息办理器:供应用户信息的存储、查询办事,和为用户指定脚色信息;
- 脚色信息办理器:供应脚色信息的存储和查询办事
- 会见掌握器:依据脚色信息和会见掌握表停止验证
FleaPHP 中已完成了上述三个部件,所以开辟者要做的功效就对照复杂了。
利用 RBAC
FleaPHP 中供应了 FLEA_Com_RBAC、FLEA_Com_RBAC_UsersManager 和 FLEA_Com_RBAC_RolesManager 三个部件,和 FLEA_Dispatcher_Auth 调剂器。
个中,FLEA_Com_RBAC_UsersManager 供应用户信息存储办事,而 FLEA_Com_RBAC_RolesManager 供应脚色信息存储办事。FLEA_Com_RBAC 则和 FLEA_Dispatcher_Auth 联合,一同供应了会见掌握才能。
上面咱们来看看 RBAC 究竟怎样任务的。
修正使用法式设置
要利用会见掌握功效,起首需求修正使用法式设置。让使用法式利用 FLEA_Dispatcher_Auth 调剂器,而不是默许的 FLEA_Dispatcher_Simple 调剂器。- <?phprequire('FLEA/FLEA.php');set_app_inf('dispatcher', 'FLEA_Dispatcher_Auth');/** * ... * 其他初始化代码 * ... */run();?>
复制代码 FLEA_Dispatcher_Auth 调剂器和 FLEA_Dispatcher_Simple 调剂器的根基功效一样。但在挪用掌握器举措办法前,FLEA_Dispatcher_Auth 调剂器会经由过程 FLEA_Com_RBAC 组件获得保留在 session 中的用户脚色信息,然后再读取掌握器的会见掌握表(ACT)。最初挪用 FLEA_Com_RBAC::check() 办法反省用户具有的脚色是不是可以会见这个掌握器及要挪用的掌握器举措。
验证经由过程,则掌握器举措办法会被挪用,不然将显示毛病信息,或挪用使用法式设置 dispatcherAuthFailedCallback 指定的毛病处置法式。
筹办掌握器的 ACT 文件
设置好使用法式后,接上去要做的就是为掌握器筹办 ACT 文件。
ACT 文件和掌握器文件同名,而且保留在统一个目次下,只是扩大名为 .act.php。例如掌握器 Controller_Default 的文件名是 Controller/Default.php,那末该掌握器的 ACT 文件名就是 Controller/Default.act.php。
ACT 文件的内容凡是利用上面的格局:- <?phpreturn array( 'allow' => 'POWER_USER, SYSTEM_ADMIN', 'actions' => array( 'remove' => array( 'allow' => 'SYSTEM_ADMIN', ), 'create' => array( 'deny' => 'SYSTEM_ADMIN', ), ),);?>
复制代码 可以看到,ACT 文件只是纯真的前往一个数组。这个数组遵守上面的格局:- array( 'allow' => '答应会见该掌握器的脚色名', 'deny' => '制止会见该掌握器的脚色名', 'actions' => array( '举措名' => array( 'allow' => '答应会见该举措的脚色名', 'deny' => '制止会见该举措的脚色名', ), // .... 更多举措 ),);
复制代码 在下面的格局中,脚色名可所以多个,例如“POWER_USER, MANAGER”。只需求用“,”分隔多个脚色名就能够了。
凡是,咱们只需求为掌握器指定 allow 或 deny 就能够了。但有时分咱们要答应多个脚色都可以会见该掌握器,但该掌握器中的特定办法只答应上述脚色中局部脚色可以会见。这时候,咱们可以经由过程'举措名' => array('allow' => '脚色名', 'deny' => '脚色名') 的体例来指定该掌握器举措独有的 ACT。
为了便于开辟,FleaPHP 预界说了几个脚色,分离是:
- RBAC_EVERYONE:暗示任何用户(不论该用户是不是具有脚色信息)
- RBAC_HAS_ROLE:暗示具有任何脚色的用户(该用户必需有脚色信息)
- RBAC_NO_ROLE:暗示不具有任何脚色的用户
- RBAC_NULL:暗示该设置没有值
出格注重,上述四个预界说脚色并非字符串,而是常量。因而必需以 'allow' => RBAC_EVERYONE 如许体例利用。而且不克不及和其他脚色混用,例如 'allow' => RBAC_EVERYONE . ', POWER_USER' 就是毛病的。
验证划定规矩
在验证时,起首从 session 中掏出用户的脚色信息。掏出来的脚色信息是一个数组,数组中每个项为用户具有的一个脚色。例如:- $userRoles = array( 'POWER_USER', 'MANAGER',);
复制代码 然后掏出掌握器的 ACT,再依照以下划定规矩停止验证:
- 假如 ACT 的 allow 为 RBAC_EVERYONE,则停止以下反省:
- 假如 ACT 的 deny 为 RBAC_NULL,则暗示暗示答应任何脚色会见,验证了局为 true;
- 假如 ACT 的 deny 为 RBAC_NO_ROLE,则暗示用户只需具有脚色信息,就能够会见。因而假如用户的脚色信息为空白,则验证了局为 false,不然验证了局为 true;
- 假如 ACT 的 deny 为 RBAC_HAS_ROLE,则暗示用户只需具有脚色信息,就不答应会见。因而假如用户的脚色信息为空白,则验证了局为 true,不然验证了局为 false;
- 假如 ACT 的 deny 为 RBAC_EVERYONE,则暗示这个 ACT 存在抵触(由于 allow 和 deny 都为 RBAC_EVERYONE);
- 反省用户的脚色名是不是呈现在 deny 指定的脚色名中,假如有,则验证了局为 false,不然验证了局为 true。
- 假如 ACT 的 allow 为 RBAC_HAS_ROLE,则暗示用户只需具有脚色信息,就能够会见。因而假如用户的脚色信息为空白,则验证了局为 false,不然验证了局为 true;
- 假如 ACT 的 allow 为 RBAC_NO_ROLE,则暗示用户只需具有脚色信息,就不答应会见。因而假如用户的脚色信息为空白,则验证了局为 true,不然验证了局为 false;
- 假如 ACT 的 allow 为 RBAC_NULL,则停止以下反省:
- 假如 ACT 的 deny 为 RBAC_NULL,则暗示 ACT 既没有设置答应会见的脚色,也没有设置回绝会见的脚色,这时候候假定为答应会见,所以验证了局为 true;
- 假如 ACT 的 deny 为 RBAC_NO_ROLE,则暗示用户只需具有脚色信息,就能够会见。因而假如用户的脚色信息为空白,则验证了局为 false,不然验证了局为 true;
- 假如 ACT 的 deny 为 RBAC_HAS_ROLE,则暗示用户只需具有脚色信息,就不答应会见。因而假如用户的脚色信息为空白,则验证了局为 true,不然验证了局为 false;
- 假如 ACT 的 deny 为 RBAC_EVERYONE,则暗示回绝任何脚色会见,验证了局为 false;
- 5) 反省用户用户的脚色名是不是呈现在 deny 指定的脚色名中,假如有,则验证了局为 false,不然验证了局为 true。
- 验证停止到这里时,ACT 的 allow 必定是脚色名,因而只需用户具有的脚色名在 allow 指定的脚色名中,验证了局就为true,不然验证了局为false。
ACT 示例
之一切停止这么庞杂的验证,是思索到多种多样的验证需求。看看上面几个例子:
- array( 'allow' => RBAC_HAS_ROLE);
复制代码- array( 'deny' => RBAC_HAS_ROLE);
复制代码
- 用户具有脚色,而且没有 POWER_USER 脚色时,答应会见:
- array( 'allow' => RBAC_HAS_ROLE, 'deny' => 'POWER_USER')
复制代码- array( 'deny' => 'MANAGER',)
复制代码
- 用户具有 POWER_USER 和 MANAGER 脚色时答应会见,但具有 SYSTEM_ADMIN 脚色时回绝会见。关于这个 ACT 界说,假如用户的脚色为 ‚POWER_USER, GUEST‘,则答应会见。假如用户的脚色为 ‚POWER_USER, SYSTEM_ADMIN‘,则不答应会见。由于 deny 的优先级老是大于 allow。
- array( 'allow' => 'POWER_USER, MANAGER', 'deny' => 'SYSTEM_ADMIN',)
复制代码 下面固然只说了对掌握器的验证,但对掌握器举措的验证划定规矩是完整不异的。只是只要当用户被答应会见掌握器时,才会对要会见的掌握器举措停止验证。这类机制供应十分高的天真性,例如:- <?phpreturn array( 'allow' => 'POWER_USER, SYSTEM_ADMIN', 'actions' => array( 'remove' => array( 'allow' => 'SYSTEM_ADMIN', ), 'create' => array( 'deny' => 'SYSTEM_ADMIN', ), ),);?>
复制代码 用户只需具有 POWER_USER 和 SYSTEM_ADMIN 两个脚色之一,就能够会见这个掌握器。但只要当用户具有 SYSTEM_ADMIN 脚色时,才答应利用掌握器的 remove 举措。反之,假如用户具有 SYSTEM_ADMIN 脚色,就不答应利用掌握器的 create 举措。
出格注重,不论是 allow 仍是 deny,只需用户具有的脚色有个中之一合适前提就会剖断该划定规矩无效。例如 'allow' => 'POWER_USER, SYSTEM_ADMIN' 只需用户具有 POWER_USER 和 SYSTEM_ADMIN 两个脚色之一,就算作答应会见。而不需求用户同时具有 POWER_USER 和 SYSTEM_ADMIN 脚色。
脚色信息存储办事
筹办好掌握器的 ACT 后,咱们还需求利用脚色信息存储办事,来办理使用法式中会用到的脚色信息。
起首,咱们要创立以下的数据表(假定利用 MySQL)。这个数据表很复杂,每行纪录存储一个脚色。- CREATE TABLE `roles` ( `role_id` INT NOT NULL AUTO_INCREMENT PRIMARY KEY , `rolename` VARCHAR( 32 ) NOT NULL , `created` INT NULL , `updated` INT NULL);
复制代码 然后咱们在使用法式中就能够从 FLEA_Com_RBAC_RolesManager 派生一个对象来办理脚色信息了:- load_class('FLEA_Com_RBAC_RolesManager');class MyRolesManager extends FLEA_Com_RBAC_RolesManager{ var $tableName = 'roles'; var $primaryKey = 'role_id';}$rolesManager =& get_singleton('MyRolesManager');/* @var $rolesManager MyRolesManager */$rolesManager->create(array('rolename' => 'SYSTEM_ADMIN'));$rolesManager->create(array('rolename' => 'POWER_USER'));$rolesManager->create(array('rolename' => 'MANAGER'));
复制代码 现实上,FLEA_Com_RBAC_RolesManager 是一个表数据进口对象,所以可以直接利用 create()、find() 等办法来添加、查询脚色信息。
用户信息存储办事
只要脚色信息,RBAC 还没法任务。咱们还需求用户信息存储办事。这些办事由 FLEA_Com_RBAC_UsersManager 来供应。起首创立存储用户信息的数据表(依然假定利用 MySQL):- CREATE TABLE `users` ( `user_id` INT NOT NULL AUTO_INCREMENT PRIMARY KEY , `username` VARCHAR( 32 ) NOT NULL , `password` VARCHAR( 64 ) NOT NULL , `email` VARCHAR( 128 ) NOT NULL , `created` INT NULL , `updated` INT NULL);
复制代码 出格注重,存储用户信息的数据表中,最少需求用户名、暗码和电子邮件地址三个字段。
然后咱们就能够很便利的存储和查询用户信息了:- load_class('FLEA_Com_RBAC_UsersManager');class MyUsersManager extends FLEA_Com_RBAC_UsersManager{ var $tableName = 'users'; var $primaryKey = 'user_id';}$usersManager =& get_singleton('MyUsersManager');/* @var $usersManager MyUsersManager */$usersManager->create(array( 'username' => 'dualface', 'password' => '12345678', 'email' => 'dualface@gmail.com',));
复制代码 下面的代码会创立一个用户名为 dualface 的用户,而暗码明文是 12345678。你或许会奇异,岂非暗码不需求加密后存储吗?
实践上,FLEA_Com_RBAC_UsersManager 为你主动完成了该项任务。FLEA_Com_RBAC_UsersManager 在创立一个用户或更新一个用户时,关于暗码字段都是出格处置的。所以法式只需求供应暗码明文就好了,而不需求本人加密。不外同时也要注重在更新用户时,不要更新暗码字段。而是应当利用 FLEA_Com_RBAC_UsersManager::changePassword() 办法来修正用户账户的暗码。
FLEA_Com_RBAC_UsersManager 采取甚么加密办法来存储暗码,是由 FLEA_Com_RBAC_UsersManager::$encodeMethod 变量决意的。默许为 PWD_CRYPT,即便用 crypt() 函数来加密。可用的加密体例还有 PWD_MD5(存储用 md5() 函数编码后的暗码)和 PWD_CLEARTEXT(存储暗码明文)。因为分歧的加密体例,生成的暗码长度都分歧,所以创立用户信息数据表时,暗码字段的长度为 64,而不是经常使用的 32。
出格注重,crypt() 函数加密的暗码超越了 32 个字符,因而必定要确保用户信息表的暗码字段有足够的长度。
假如用户信息表的用户名、暗码和电子邮件地址三个字段不是默许的 username、password 和 email,那末要分离经由过程 FLEA_Com_RBAC_UsersManager::$usernameField、FLEA_Com_RBAC_UsersManager::$passwordField 和 FLEA_Com_RBAC_UsersManager::$emailField 变量来指定。
FLEA_Com_RBAC_UsersManager 固然也是一个表数据进口,然而供应了 findByUserId()、findByUsername、findByEmail 等便当的办法。请参考 API 文档中的 FLEA_Com_RBAC_UsersManager 类,懂得一切便当办法。
为用户指定脚色
有了用户和脚色信息,咱们还需求将用户信息和脚色信息联系关系起来。这依然是经由过程 FLEA_Com_RBAC_UsersManager 来完成。
起首也是创立一个数据表,用来存储用户和脚色之间的联系关系关系:- CREATE TABLE `roles_users` ( `user_id` INT NOT NULL , `role_id` INT NOT NULL , PRIMARY KEY ( `user_id` , `role_id` ));
复制代码 接上去修正咱们的 FLEA_Com_RBAC_UsersManager 承继类:- load_class('FLEA_Com_RBAC_UsersManager');class MyUsersManager extends FLEA_Com_RBAC_UsersManager{ var $tableName = 'users'; var $primaryKey = 'user_id'; var $rolesFields = 'roles'; var $manyToMany = array( 'tableClass' => 'MyRolesManager', 'mappingName' => 'roles', 'joinTable' => 'roles_users', );}
复制代码 新增添的一个 MANY_TO_MANY 用于将用户和脚色联系关系起来。**注重 MANY_TO_MANY 联系关系的 mappingName 选项必定要和 $rolesFields 变量的值一样。不然用 FLEA_Com_RBAC_UsersManager::fetchRoles() 没法获得用户的脚色信息。
不外只是如许的界说,还不克不及实践利用。咱们看一段实践利用的代码:- <?phprequire('FLEA/FLEA.php');// 假定命据库毗连信息保留在 APP/Config/DSN.php 文件中register_app_inf('APP/Config/DSN.php');load_class('FLEA_Com_RBAC_RolesManager');class MyRolesManager extends FLEA_Com_RBAC_RolesManager{ var $tableName = 'roles'; var $primaryKey = 'role_id';}load_class('FLEA_Com_RBAC_UsersManager');class MyUsersManager extends FLEA_Com_RBAC_UsersManager{ var $tableName = 'users'; var $primaryKey = 'user_id'; var $manyToMany = array( 'tableClass' => 'MyRolesManager', 'mappingName' => 'roles', 'joinTable' => 'roles_users', );}$usersManager =& get_singleton('MyUsersManager');/* @var $usersManager MyUsersManager */// 掏出用户$user = $usersManager->findByUsername('dualface');// 清空现有的脚色信息$user[$usersManager->rolesField] = array();// 掏出 POWER_USER 脚色$rolesManager =& get_singleton('MyRolesManager');/* @var rolesManager MyRolesManager */$role = $rolesManager->find(array('rolename' => 'POWER_USER'));// 指定给用户$user[$usersManager->rolesField][] = $role[$rolesManager->primaryKey];// 掏出 MANAGER 脚色$role = $rolesManager->find(array('rolename' => 'MANAGER'));// 指定给用户$user[$usersManager->rolesField][] = $role[$rolesManager->primaryKey];// 保留修正后的用户信息$usersManager->update($user);// 从头从数据库读取用户信息,肯定为用户指定的脚色信息已保留到数据库$user = $usersManager->findByUsername('dualface');dump($user);
复制代码 运转这段代码,可以看到为用户指定的脚色信息,的确保留到数据库了:
凡是,咱们会在使用法式中供应一个办理界面,用于办理用户信息,而且可觉得用户指定脚色。如许的办理界面相似下图:
上图中的权限实践上就是可以给用户指定的脚色,只不外换了一个称呼罢了。
用户登录
因为要利用 RBAC 组件停止会见掌握,所以咱们的用户登录局部要多写几行代码。罕见的登录代码以下:- <?phprequire('FLEA/FLEA.php');// 假定命据库毗连信息保留在 APP/Config/DSN.php 文件中register_app_inf('APP/Config/DSN.php');load_class('FLEA_Com_RBAC_RolesManager');class MyRolesManager extends FLEA_Com_RBAC_RolesManager{ var $tableName = 'roles'; var $primaryKey = 'role_id';}load_class('FLEA_Com_RBAC_UsersManager');class MyUsersManager extends FLEA_Com_RBAC_UsersManager{ var $tableName = 'users'; var $primaryKey = 'user_id'; var $manyToMany = array( 'tableClass' => 'MyRolesManager', 'mappingName' => 'roles', 'joinTable' => 'roles_users', );}/** * 摹拟登录 */login('dualface', '12345678');/** * 处置用户登录 */function login($username, $password) { $usersManager =& get_singleton('MyUsersManager'); /* @var $usersManager MyUsersManager */ // 验证用户名和暗码是不是准确 $user = $usersManager->findByUsername($username); if (!$user || !$usersManager->checkPassword($password, $user[$usersManager->passwordField])) { echo "Username invalid or password mismatch."; exit; } // 获得用户脚色信息 $roles = $usersManager->fetchRoles($user); // 取得 FLEA_Com_RBAC 组件实例 $rbac =& get_singleton('FLEA_Com_RBAC'); /* @var $rbac FLEA_Com_RBAC */ // 为了下降办事器承当,咱们只在 session 中存储用户ID和用户名 $sessionUser = array( 'USERID' => $user[$usersManager->primaryKey], 'USERNAME' => $user[$usersManager->usernameField], ); // 将用户ID、用户名和脚色信息保留到 session $rbac->setUser($sessionUser, $roles); // 登录胜利 echo "Login successed, contents of session:"; dump(若何利用 RBAC 组件?
- [b]请务必更新到 1.0.60.553 版本以上,确保 RBAC 组件与文档中的描写符合合[/b]
- RBAC 是英文(Role-Based Access Control)的缩写,也就是基于脚色的会见掌握。RBAC 的界说对照流畅,我就以对照活泼的模式来论述甚么是 RBAC。
- [size=5]ATM 机的一天[/size]
- 假定有一台 ATM(主动提款机)放在街边,咱们来看看这个 ATM 渡过的一天。
- [list=1]
- [*]早上,有一个家伙走到 ATM 眼前,对着机械说:“芝麻开门,芝麻开门,给我 100 块!”。很明显 ATM 不会有任何举措。绝望之余,这个家伙踢了 ATM 一脚走了。
- [*]午时,一名大度的 Office lady 走到 ATM 机眼前,放入她的信誉卡,输出暗码后,掏出了 1200 块钱。固然,这些钱很快就会酿成一件衣服或是化装品。
- [*]上班时分,银行的任务人员离开 ATM 机械眼前,放入一张特制的磁卡,然后输出暗码。从中查询到 ATM 机械内还有充分的现金,无需增补。所以他很乐意的开着车去下一台 ATM 机械地点地了。
- [/list]如今咱们要开辟一台具有一样功效的 ATM 机,应当怎样做呢?
- 起首,咱们的 ATM 机不克不及让人随意取钱,否则银行会破产的。接上去,ATM 机需求一个让人们放入磁卡并输出暗码的装备。人们放入磁卡并输出暗码后,ATM 机还要可以判别这张磁卡的卡号和暗码是不是无效,而且婚配。以后,ATM 机必需判别磁卡的卡号属于哪一种类型,假如是信誉卡,那末则显示查询账户余额和取款的界面。假如是特制的磁卡,则显示 ATM 机内的现金余额。
- [size=5]ATM 与 RBAC[/size]
- 下面的例子显得有点怪诞,然而倒是一个典范的基于脚色的会见掌握。
- [list=1]
- [*]关于没有磁卡或输出了毛病暗码的用户,一概回绝办事,也就是不答应停止任何其他操作;
- [*]假如输出了准确的暗码,必需判别用户输出哪种类型,并供应响应的办事界面;
- [*]假如用户测验考试会见本人不克不及利用的办事,那末要明白告知用户这是不成能的。
- [/list]这个流程中,一共呈现了两种脚色:[b]信誉卡用户[/b]和[b]办理卡用户[/b]。而那些没有磁卡的用户,都属于[b]没有脚色[/b]一类。RBAC 要可以任务,最少需求两个数据:[b]脚色信息[/b]和[b]会见掌握表[/b]。
- [b]脚色信息[/b]凡是是指某个用户具有的脚色,例如你持有一张信誉卡,那末你就具有“信誉卡用户”这个脚色。假如你持有一张办理卡,那末你就具有“办理卡用户”这个脚色。假如你既没有信誉卡,又没有办理卡,那末你就没有上述两种脚色。
- 有了脚色信息,RBAC 体系还需求一个会见掌握表。[b]会见掌握表(Access Control Table)[/b]是一组数据,用于指出哪些脚色可使用哪一个功效,哪些脚色不克不及利用哪一个功效。例如在 ATM 机中,具有“信誉卡用户”脚色,就能够利用查询账户余额和取款两项功效;而具有“办理卡用户”脚色,就能够利用查询 ATM 机内现金余额的动能。
- 咱们来摹拟一次 ATM 机的操作:
- [list=1]
- [*]唐雷有一张信誉卡,他放入 ATM 机并输出了准确的暗码。这时候,他被 ATM 机以为具有“信誉卡用户”脚色。
- [*]依据下面的判别了局,ATM 机显示了一个操作界面,下面有查询账户余额和取款两项操作按钮。
- [*]唐雷按下了“查询账户余额”按钮,ATM 机的查询账户余额功效被挪用。
- [*]在查询账户余额功效中,再次反省用户的脚色信息,肯定他可使用这个功效。
- [*]停止一系列操作,然后将唐雷信誉卡账户上的余额数字显示到屏幕上。
- [*]唐雷很愁闷他的信誉卡又透支了,悻悻然掏出卡走人了。这时候 ATM 主动排除以后的脚色信息,为下一次操作做好筹办。
- [/list]从下面可以看出,RBAC 充任了体系的一道平安樊篱。一切的操作都需求进过 RBAC 验证事后才干利用。如许充实包管了体系的平安性。
- [size=5]RBAC 概念[/size]
- 在 FleaPHP 的 RBAC 组件中,只要以下几项概念需求了解:
- [list]
- [*][b]用户[/b]:使用法式的利用者;
- [*][b]脚色[/b]:一个名字,可觉得用户指定多个脚色(0-n);
- [*][b]会见掌握表(ACT)[/b]:一个数组,用来指明哪些功效可以被哪些脚色会见或限制会见。
- [/list]除上述三个概念,要想 RBAC 体系可以正常任务,还需求用户信息办理器、脚色信息办理器和会见掌握器三个部件。
- [list]
- [*][b]用户信息办理器[/b]:供应用户信息的存储、查询办事,和为用户指定脚色信息;
- [*][b]脚色信息办理器[/b]:供应脚色信息的存储和查询办事
- [*][b]会见掌握器[/b]:依据脚色信息和会见掌握表停止验证
- [/list]FleaPHP 中已完成了上述三个部件,所以开辟者要做的功效就对照复杂了。
- [size=5]利用 RBAC[/size]
- FleaPHP 中供应了 FLEA_Com_RBAC、FLEA_Com_RBAC_UsersManager 和 FLEA_Com_RBAC_RolesManager 三个部件,和 FLEA_Dispatcher_Auth 调剂器。
- 个中,FLEA_Com_RBAC_UsersManager 供应用户信息存储办事,而 FLEA_Com_RBAC_RolesManager 供应脚色信息存储办事。FLEA_Com_RBAC 则和 FLEA_Dispatcher_Auth 联合,一同供应了会见掌握才能。
- 上面咱们来看看 RBAC 究竟怎样任务的。
- [size=4]修正使用法式设置[/size]
- 要利用会见掌握功效,起首需求修正使用法式设置。让使用法式利用 FLEA_Dispatcher_Auth 调剂器,而不是默许的 FLEA_Dispatcher_Simple 调剂器。
- [code]<?phprequire('FLEA/FLEA.php');set_app_inf('dispatcher', 'FLEA_Dispatcher_Auth');/** * ... * 其他初始化代码 * ... */run();?>
复制代码 FLEA_Dispatcher_Auth 调剂器和 FLEA_Dispatcher_Simple 调剂器的根基功效一样。但在挪用掌握器举措办法前,FLEA_Dispatcher_Auth 调剂器会经由过程 FLEA_Com_RBAC 组件获得保留在 session 中的用户脚色信息,然后再读取掌握器的会见掌握表(ACT)。最初挪用 FLEA_Com_RBAC::check() 办法反省用户具有的脚色是不是可以会见这个掌握器及要挪用的掌握器举措。
验证经由过程,则掌握器举措办法会被挪用,不然将显示毛病信息,或挪用使用法式设置 dispatcherAuthFailedCallback 指定的毛病处置法式。
筹办掌握器的 ACT 文件
设置好使用法式后,接上去要做的就是为掌握器筹办 ACT 文件。
ACT 文件和掌握器文件同名,而且保留在统一个目次下,只是扩大名为 .act.php。例如掌握器 Controller_Default 的文件名是 Controller/Default.php,那末该掌握器的 ACT 文件名就是 Controller/Default.act.php。
ACT 文件的内容凡是利用上面的格局:- <?phpreturn array( 'allow' => 'POWER_USER, SYSTEM_ADMIN', 'actions' => array( 'remove' => array( 'allow' => 'SYSTEM_ADMIN', ), 'create' => array( 'deny' => 'SYSTEM_ADMIN', ), ),);?>
复制代码 可以看到,ACT 文件只是纯真的前往一个数组。这个数组遵守上面的格局:- array( 'allow' => '答应会见该掌握器的脚色名', 'deny' => '制止会见该掌握器的脚色名', 'actions' => array( '举措名' => array( 'allow' => '答应会见该举措的脚色名', 'deny' => '制止会见该举措的脚色名', ), // .... 更多举措 ),);
复制代码 在下面的格局中,脚色名可所以多个,例如“POWER_USER, MANAGER”。只需求用“,”分隔多个脚色名就能够了。
凡是,咱们只需求为掌握器指定 allow 或 deny 就能够了。但有时分咱们要答应多个脚色都可以会见该掌握器,但该掌握器中的特定办法只答应上述脚色中局部脚色可以会见。这时候,咱们可以经由过程'举措名' => array('allow' => '脚色名', 'deny' => '脚色名') 的体例来指定该掌握器举措独有的 ACT。
为了便于开辟,FleaPHP 预界说了几个脚色,分离是:
- RBAC_EVERYONE:暗示任何用户(不论该用户是不是具有脚色信息)
- RBAC_HAS_ROLE:暗示具有任何脚色的用户(该用户必需有脚色信息)
- RBAC_NO_ROLE:暗示不具有任何脚色的用户
- RBAC_NULL:暗示该设置没有值
出格注重,上述四个预界说脚色并非字符串,而是常量。因而必需以 'allow' => RBAC_EVERYONE 如许体例利用。而且不克不及和其他脚色混用,例如 'allow' => RBAC_EVERYONE . ', POWER_USER' 就是毛病的。
验证划定规矩
在验证时,起首从 session 中掏出用户的脚色信息。掏出来的脚色信息是一个数组,数组中每个项为用户具有的一个脚色。例如:- $userRoles = array( 'POWER_USER', 'MANAGER',);
复制代码 然后掏出掌握器的 ACT,再依照以下划定规矩停止验证:
- 假如 ACT 的 allow 为 RBAC_EVERYONE,则停止以下反省:
- 假如 ACT 的 deny 为 RBAC_NULL,则暗示暗示答应任何脚色会见,验证了局为 true;
- 假如 ACT 的 deny 为 RBAC_NO_ROLE,则暗示用户只需具有脚色信息,就能够会见。因而假如用户的脚色信息为空白,则验证了局为 false,不然验证了局为 true;
- 假如 ACT 的 deny 为 RBAC_HAS_ROLE,则暗示用户只需具有脚色信息,就不答应会见。因而假如用户的脚色信息为空白,则验证了局为 true,不然验证了局为 false;
- 假如 ACT 的 deny 为 RBAC_EVERYONE,则暗示这个 ACT 存在抵触(由于 allow 和 deny 都为 RBAC_EVERYONE);
- 反省用户的脚色名是不是呈现在 deny 指定的脚色名中,假如有,则验证了局为 false,不然验证了局为 true。
- 假如 ACT 的 allow 为 RBAC_HAS_ROLE,则暗示用户只需具有脚色信息,就能够会见。因而假如用户的脚色信息为空白,则验证了局为 false,不然验证了局为 true;
- 假如 ACT 的 allow 为 RBAC_NO_ROLE,则暗示用户只需具有脚色信息,就不答应会见。因而假如用户的脚色信息为空白,则验证了局为 true,不然验证了局为 false;
- 假如 ACT 的 allow 为 RBAC_NULL,则停止以下反省:
- 假如 ACT 的 deny 为 RBAC_NULL,则暗示 ACT 既没有设置答应会见的脚色,也没有设置回绝会见的脚色,这时候候假定为答应会见,所以验证了局为 true;
- 假如 ACT 的 deny 为 RBAC_NO_ROLE,则暗示用户只需具有脚色信息,就能够会见。因而假如用户的脚色信息为空白,则验证了局为 false,不然验证了局为 true;
- 假如 ACT 的 deny 为 RBAC_HAS_ROLE,则暗示用户只需具有脚色信息,就不答应会见。因而假如用户的脚色信息为空白,则验证了局为 true,不然验证了局为 false;
- 假如 ACT 的 deny 为 RBAC_EVERYONE,则暗示回绝任何脚色会见,验证了局为 false;
- 5) 反省用户用户的脚色名是不是呈现在 deny 指定的脚色名中,假如有,则验证了局为 false,不然验证了局为 true。
- 验证停止到这里时,ACT 的 allow 必定是脚色名,因而只需用户具有的脚色名在 allow 指定的脚色名中,验证了局就为true,不然验证了局为false。
ACT 示例
之一切停止这么庞杂的验证,是思索到多种多样的验证需求。看看上面几个例子:
- array( 'allow' => RBAC_HAS_ROLE);
复制代码- array( 'deny' => RBAC_HAS_ROLE);
复制代码
- 用户具有脚色,而且没有 POWER_USER 脚色时,答应会见:
- array( 'allow' => RBAC_HAS_ROLE, 'deny' => 'POWER_USER')
复制代码- array( 'deny' => 'MANAGER',)
复制代码
- 用户具有 POWER_USER 和 MANAGER 脚色时答应会见,但具有 SYSTEM_ADMIN 脚色时回绝会见。关于这个 ACT 界说,假如用户的脚色为 ‚POWER_USER, GUEST‘,则答应会见。假如用户的脚色为 ‚POWER_USER, SYSTEM_ADMIN‘,则不答应会见。由于 deny 的优先级老是大于 allow。
- array( 'allow' => 'POWER_USER, MANAGER', 'deny' => 'SYSTEM_ADMIN',)
复制代码 下面固然只说了对掌握器的验证,但对掌握器举措的验证划定规矩是完整不异的。只是只要当用户被答应会见掌握器时,才会对要会见的掌握器举措停止验证。这类机制供应十分高的天真性,例如:- <?phpreturn array( 'allow' => 'POWER_USER, SYSTEM_ADMIN', 'actions' => array( 'remove' => array( 'allow' => 'SYSTEM_ADMIN', ), 'create' => array( 'deny' => 'SYSTEM_ADMIN', ), ),);?>
复制代码 用户只需具有 POWER_USER 和 SYSTEM_ADMIN 两个脚色之一,就能够会见这个掌握器。但只要当用户具有 SYSTEM_ADMIN 脚色时,才答应利用掌握器的 remove 举措。反之,假如用户具有 SYSTEM_ADMIN 脚色,就不答应利用掌握器的 create 举措。
出格注重,不论是 allow 仍是 deny,只需用户具有的脚色有个中之一合适前提就会剖断该划定规矩无效。例如 'allow' => 'POWER_USER, SYSTEM_ADMIN' 只需用户具有 POWER_USER 和 SYSTEM_ADMIN 两个脚色之一,就算作答应会见。而不需求用户同时具有 POWER_USER 和 SYSTEM_ADMIN 脚色。
脚色信息存储办事
筹办好掌握器的 ACT 后,咱们还需求利用脚色信息存储办事,来办理使用法式中会用到的脚色信息。
起首,咱们要创立以下的数据表(假定利用 MySQL)。这个数据表很复杂,每行纪录存储一个脚色。- CREATE TABLE `roles` ( `role_id` INT NOT NULL AUTO_INCREMENT PRIMARY KEY , `rolename` VARCHAR( 32 ) NOT NULL , `created` INT NULL , `updated` INT NULL);
复制代码 然后咱们在使用法式中就能够从 FLEA_Com_RBAC_RolesManager 派生一个对象来办理脚色信息了:- load_class('FLEA_Com_RBAC_RolesManager');class MyRolesManager extends FLEA_Com_RBAC_RolesManager{ var $tableName = 'roles'; var $primaryKey = 'role_id';}$rolesManager =& get_singleton('MyRolesManager');/* @var $rolesManager MyRolesManager */$rolesManager->create(array('rolename' => 'SYSTEM_ADMIN'));$rolesManager->create(array('rolename' => 'POWER_USER'));$rolesManager->create(array('rolename' => 'MANAGER'));
复制代码 现实上,FLEA_Com_RBAC_RolesManager 是一个表数据进口对象,所以可以直接利用 create()、find() 等办法来添加、查询脚色信息。
用户信息存储办事
只要脚色信息,RBAC 还没法任务。咱们还需求用户信息存储办事。这些办事由 FLEA_Com_RBAC_UsersManager 来供应。起首创立存储用户信息的数据表(依然假定利用 MySQL):- CREATE TABLE `users` ( `user_id` INT NOT NULL AUTO_INCREMENT PRIMARY KEY , `username` VARCHAR( 32 ) NOT NULL , `password` VARCHAR( 64 ) NOT NULL , `email` VARCHAR( 128 ) NOT NULL , `created` INT NULL , `updated` INT NULL);
复制代码 出格注重,存储用户信息的数据表中,最少需求用户名、暗码和电子邮件地址三个字段。
然后咱们就能够很便利的存储和查询用户信息了:- load_class('FLEA_Com_RBAC_UsersManager');class MyUsersManager extends FLEA_Com_RBAC_UsersManager{ var $tableName = 'users'; var $primaryKey = 'user_id';}$usersManager =& get_singleton('MyUsersManager');/* @var $usersManager MyUsersManager */$usersManager->create(array( 'username' => 'dualface', 'password' => '12345678', 'email' => 'dualface@gmail.com',));
复制代码 下面的代码会创立一个用户名为 dualface 的用户,而暗码明文是 12345678。你或许会奇异,岂非暗码不需求加密后存储吗?
实践上,FLEA_Com_RBAC_UsersManager 为你主动完成了该项任务。FLEA_Com_RBAC_UsersManager 在创立一个用户或更新一个用户时,关于暗码字段都是出格处置的。所以法式只需求供应暗码明文就好了,而不需求本人加密。不外同时也要注重在更新用户时,不要更新暗码字段。而是应当利用 FLEA_Com_RBAC_UsersManager::changePassword() 办法来修正用户账户的暗码。
FLEA_Com_RBAC_UsersManager 采取甚么加密办法来存储暗码,是由 FLEA_Com_RBAC_UsersManager::$encodeMethod 变量决意的。默许为 PWD_CRYPT,即便用 crypt() 函数来加密。可用的加密体例还有 PWD_MD5(存储用 md5() 函数编码后的暗码)和 PWD_CLEARTEXT(存储暗码明文)。因为分歧的加密体例,生成的暗码长度都分歧,所以创立用户信息数据表时,暗码字段的长度为 64,而不是经常使用的 32。
出格注重,crypt() 函数加密的暗码超越了 32 个字符,因而必定要确保用户信息表的暗码字段有足够的长度。
假如用户信息表的用户名、暗码和电子邮件地址三个字段不是默许的 username、password 和 email,那末要分离经由过程 FLEA_Com_RBAC_UsersManager::$usernameField、FLEA_Com_RBAC_UsersManager::$passwordField 和 FLEA_Com_RBAC_UsersManager::$emailField 变量来指定。
FLEA_Com_RBAC_UsersManager 固然也是一个表数据进口,然而供应了 findByUserId()、findByUsername、findByEmail 等便当的办法。请参考 API 文档中的 FLEA_Com_RBAC_UsersManager 类,懂得一切便当办法。
为用户指定脚色
有了用户和脚色信息,咱们还需求将用户信息和脚色信息联系关系起来。这依然是经由过程 FLEA_Com_RBAC_UsersManager 来完成。
起首也是创立一个数据表,用来存储用户和脚色之间的联系关系关系:- CREATE TABLE `roles_users` ( `user_id` INT NOT NULL , `role_id` INT NOT NULL , PRIMARY KEY ( `user_id` , `role_id` ));
复制代码 接上去修正咱们的 FLEA_Com_RBAC_UsersManager 承继类:- load_class('FLEA_Com_RBAC_UsersManager');class MyUsersManager extends FLEA_Com_RBAC_UsersManager{ var $tableName = 'users'; var $primaryKey = 'user_id'; var $rolesFields = 'roles'; var $manyToMany = array( 'tableClass' => 'MyRolesManager', 'mappingName' => 'roles', 'joinTable' => 'roles_users', );}
复制代码 新增添的一个 MANY_TO_MANY 用于将用户和脚色联系关系起来。**注重 MANY_TO_MANY 联系关系的 mappingName 选项必定要和 $rolesFields 变量的值一样。不然用 FLEA_Com_RBAC_UsersManager::fetchRoles() 没法获得用户的脚色信息。
不外只是如许的界说,还不克不及实践利用。咱们看一段实践利用的代码:- <?phprequire('FLEA/FLEA.php');// 假定命据库毗连信息保留在 APP/Config/DSN.php 文件中register_app_inf('APP/Config/DSN.php');load_class('FLEA_Com_RBAC_RolesManager');class MyRolesManager extends FLEA_Com_RBAC_RolesManager{ var $tableName = 'roles'; var $primaryKey = 'role_id';}load_class('FLEA_Com_RBAC_UsersManager');class MyUsersManager extends FLEA_Com_RBAC_UsersManager{ var $tableName = 'users'; var $primaryKey = 'user_id'; var $manyToMany = array( 'tableClass' => 'MyRolesManager', 'mappingName' => 'roles', 'joinTable' => 'roles_users', );}$usersManager =& get_singleton('MyUsersManager');/* @var $usersManager MyUsersManager */// 掏出用户$user = $usersManager->findByUsername('dualface');// 清空现有的脚色信息$user[$usersManager->rolesField] = array();// 掏出 POWER_USER 脚色$rolesManager =& get_singleton('MyRolesManager');/* @var rolesManager MyRolesManager */$role = $rolesManager->find(array('rolename' => 'POWER_USER'));// 指定给用户$user[$usersManager->rolesField][] = $role[$rolesManager->primaryKey];// 掏出 MANAGER 脚色$role = $rolesManager->find(array('rolename' => 'MANAGER'));// 指定给用户$user[$usersManager->rolesField][] = $role[$rolesManager->primaryKey];// 保留修正后的用户信息$usersManager->update($user);// 从头从数据库读取用户信息,肯定为用户指定的脚色信息已保留到数据库$user = $usersManager->findByUsername('dualface');dump($user);
复制代码 运转这段代码,可以看到为用户指定的脚色信息,的确保留到数据库了:
凡是,咱们会在使用法式中供应一个办理界面,用于办理用户信息,而且可觉得用户指定脚色。如许的办理界面相似下图:
上图中的权限实践上就是可以给用户指定的脚色,只不外换了一个称呼罢了。
用户登录
因为要利用 RBAC 组件停止会见掌握,所以咱们的用户登录局部要多写几行代码。罕见的登录代码以下:下面的代码中第一次呈现了对 FLEA_Com_RBAC 的利用。凡是咱们只需求用到 FLEA_Com_RBAC::setUser() 办法。这个办法将用户信息和对应的脚色信息保留到 session。为了勤俭办事器资本,咱们要尽可能削减保留在 session 中的内容。
运转这个剧本,可以看到以下的输入:
人人在开辟本人的使用法式时,根基上可以把 login() 函数的内容照搬曩昔。
用户刊出
处置用户刊出十分复杂,凡是用 session_destroy() 烧毁 session 数据就能够了。假如只想排除用户登录信息,而不影响 session 中的其他信息,可以用上面两行代码:- $rbac =& get_singleton('FLEA_Com_RBAC');$rbac->clearUser();
复制代码 完成会见掌握
实践上,做完下面几个步调,咱们的 RBAC 已可以任务了。你可以测验考试登录体系,然后会见那些遭到回护的掌握器。然后再从体系刊出后,从头会见受回护的掌握器。
今朝,FleaPHP 的 RBAC 在处置 ACT 上,还不敷天真。每一个掌握器的 ACT 都是从文件载入的,而不是从数据库。但有伶俐的开辟者已想出了变通的做法。
那就是把从数据库获得掌握器 ACT 的代码写在掌握器的 .act.php 文件中,例如:
APP\Controller\MyController.act.php- <?php$modelACT =& get_singleton('Model_ControllerACTProvider');/* @var $modelACT Model_ControllerACTProvider */return $modelACT->getACT('MyController');?>
复制代码 固然,咱们还要完成一个 Model_ControllerACTProvider 表数据进口:- <?phpload_class('FLEA_Db_TableDataGateway');class Model_ControllerACTProvider extends FLEA_Db_TableDataGateway{ var $tableName = 'controller_acts'; var $primaryKey = 'controller_name'; function getACT($controllerName) { $row = parent::find(array($this->primaryKey => strtoupper($controllerName))); return unserialize($row['act']); } function setACT($controllerName, $ACT) { $row = array( $this->primaryKey => strtoupper($controllerName), 'act' => serialize($ACT) ); return parent::create($row); }}?>
复制代码 和一个数据表:- CREATE TABLE `controller_acts` ( `controller_name` VARCHAR( 32 ) NOT NULL , `act` TEXT NOT NULL , `created` INT NULL , `updated` INT NULL , PRIMARY KEY ( `controller_name` ))
复制代码 如许一来,咱们就能够在数据库中保留掌握器的 ACT 了。
SESSION);}?>[/code]下面的代码中第一次呈现了对 FLEA_Com_RBAC 的利用。凡是咱们只需求用到 FLEA_Com_RBAC::setUser() 办法。这个办法将用户信息和对应的脚色信息保留到 session。为了勤俭办事器资本,咱们要尽可能削减保留在 session 中的内容。
运转这个剧本,可以看到以下的输入:
人人在开辟本人的使用法式时,根基上可以把 login() 函数的内容照搬曩昔。
用户刊出
处置用户刊出十分复杂,凡是用 session_destroy() 烧毁 session 数据就能够了。假如只想排除用户登录信息,而不影响 session 中的其他信息,可以用上面两行代码:完成会见掌握
实践上,做完下面几个步调,咱们的 RBAC 已可以任务了。你可以测验考试登录体系,然后会见那些遭到回护的掌握器。然后再从体系刊出后,从头会见受回护的掌握器。
今朝,FleaPHP 的 RBAC 在处置 ACT 上,还不敷天真。每一个掌握器的 ACT 都是从文件载入的,而不是从数据库。但有伶俐的开辟者已想出了变通的做法。
那就是把从数据库获得掌握器 ACT 的代码写在掌握器的 .act.php 文件中,例如:
APP\Controller\MyController.act.php固然,咱们还要完成一个 Model_ControllerACTProvider 表数据进口:和一个数据表:如许一来,咱们就能够在数据库中保留掌握器的 ACT 了。
基础这个东西,有人问学php需要任何基础不? |
|