ACCESSRBAC

出自

https://www.lyblog.net/detail/552.html

 

RBAC是怎么样,能迎刃而解什么难题?

RBAC是Role-Based Access
Control的首字母,译成闽南语即基于角色的权柄访问控制,说白了也就是用户通过角色与权力进行关联[其架构灵感来源操作系统的GBAC(GROUP-Based
Access
Control)的权杖管理控制]。简单的来说,一个用户可以拥有多少角色,每一个角色有所多少权力。这样,就社团成“用户-角色-权限”的授权模型。在这种模型中,用户与角色之间,角色与权力以内,一般者是多对多的关联。其对应提到如下:

ACCESS 1

在很多的其实应用中,系统不仅是急需用户完成简单的挂号,还亟需对两样级其余用户对两样资源的访问具有不同的操作权限。且在信用社开支中,权限管理序列也成了再次支付效率最高的一个模块之一。而在多套系统中,对应的权柄管理只好知足自己系统的保管需要,无论是在数据库设计、权限访问和权力管理机制模式上都可能不同,这种不致性也就存在如下的憋端:

  • 珍惜多套系统,重复造轮子,时间没用在刀刃上
  • 用户管理、社团机制等数据重复维护,数据的完整性、一致性很难取得保持
  • 权限系统规划不同,概念领会不同,及相应技术差距,系统里面集成存在问题,单点登录难度大,也复杂的商号系统带来不便

RBAC是依照不断实施之后,指出的一个相比成熟的访问控制方案。实践注明,接纳基于RBAC模型的权位管理连串具备以下优势:由于角色、权限以内的转变比角色、用户关系里面的转变相对要慢得多,减小了授权管理的繁杂,降低管理支出;而且可以灵活地协理使用系统的安全策略,并对应用系列的变通有很大的紧缩性;在操作上,权限分配直观、容易通晓,便于使用;分级权限适合分层的用户级格局;重用性强。

ThinkPHP中RBAC实现系统

ThinkPHP中RBAC基于Java的Spring的Acegi安全系统作为参考原型,并做了对应的简化处理,以适应现阶段的ThinkPHP结构,提供一个多层、可定制的安全连串来为利用开发提供安全控制。安全系列中重点有以下几有些:

  • 安然拦截器
  • 表达管理器
  • 决策访问管理器
  • 运行地方管理器

有惊无险拦截器

平安拦截器就好比一道道门,在系统的安全防护系统中恐怕存在重重不同的安全控制环节,一旦某个环节你未经过平安系列认证,那么安全拦截器就会执行拦截。

表达管理器

 

制止系统的首先道门就是注明管理器,认证管理器负责控制你是什么人,一般它通过认证你的基本点(平时是一个用户名)和你的凭证(通常是一个密码),或者更多的素材来形成。更一言以蔽之,认证管理器验证你的身价是否在平安戒备系列授权范围以内。

走访决策管理

 

即使如此经过了验证管理器的身份验证,然而并不意味你可以在系统里面肆意妄为,因为你还需要经过拜访决策管理这道门。访问决策管理器对用户展开授权,通过考虑你的身价验证信息和与受保障资源事关的景德镇性能决定是是否可以进来系统的某部模块,和拓展某项操作。例如,安全规则规定只有主管才同意访问某个模块,而你并不曾被给予经理权限,那么安全拦截器会阻止你的造访操作。
表决访问管理器不可以独立运行,必须首先看重认证管理器举行身份确认,因而,在加载访问决策过滤器的时候曾经包含了表达管理器和仲裁访问管理器。 
为了知足使用的不比需要,ThinkPHP
在展开访问决策管理的时候使用二种情势:登录形式和及时情势。登录形式,系统在用户登录的时候读取改用户所所有的授权信息到
Session,下次不再重复拿到授权信息。也就是说即便管理员对该用户举行了权力修改,用户也必须在下次登录后才能见效。即时格局就是为了化解地点的问题,在每便访问系统的模块或者操作时候,进行尽管验证该用户是否持有该模块和操作的授权,从更高品位上保持了系统的安全。

运作地方管理器

 

运行地方管理器的用途在多数利用系统中是少数的,例如某个操作和模块需要两个地点的平安需求,运行地方管理器可以用另一个身份替换你眼前的地位,从而允许你拜访应用体系里面更深处的受保障目的。这一层安全系统近日的
RBAC 中从不落实。

ThinkPHP中RBAC认证流程

对应下面的平安体系,ThinkPHP 的 RBAC 认证的经过大概如下:

  1. 认清当前模块的脚下操作是否需要表明
  2. 假若急需证实并且没有登录,跳到表达网关,如果已经登录 执行5
  3. 通过委托表明举行用户身份认证
  4. 取得用户的核定访问列表
  5. 判断当前用户是否持有访问权限

权力管理的现实落实过程

RBAC相关的数据库介绍

在ThinkPHP完整包,包含了RBAC处理类RBAC.class.php文件,位于Extend/Library/ORG/Util。打开该公文,其中就带有了运用RBAC必备的4张表,SQL语句如下(复制后请替换表前缀):

复制

  1. CREATE TABLE IF NOT EXISTS `ly_access` (
  2. `role_id`
    smallint(6) unsigned NOT NULL,
  3. `node_id`
    smallint(6) unsigned NOT NULL,
  4. `level`
    tinyint(1) NOT NULL,
  5. `module`
    varchar(50) DEFAULT NULL,
  6. KEY `groupId` (`role_id`),
  7. KEY `nodeId` (`node_id`)
  8. ) ENGINE=MyISAM DEFAULT CHARSET=utf8;
  9.  
  10. CREATE TABLE IF NOT EXISTS `ly_node` (
  11. `id`
    smallint(6) unsigned NOT NULL AUTO_INCREMENT,
  12. `name`
    varchar(20) NOT NULL,
  13. `title`
    varchar(50) DEFAULT NULL,
  14. `ACCESS,status`
    tinyint(1) DEFAULT ‘0’,
  15. `remark`
    varchar(255) DEFAULT NULL,
  16. `sort`
    smallint(6) unsigned DEFAULT NULL,
  17. `pid`
    smallint(6) unsigned NOT NULL,
  18. `level`
    tinyint(1) unsigned NOT NULL,
  19. PRIMARY KEY (`id`),
  20. KEY `level`
    (`level`),
  21. KEY `pid`
    (`pid`),
  22. KEY `status` (`status`),
  23. KEY `name`
    (`name`)
  24. ) ENGINE=MyISAM DEFAULT CHARSET=utf8;
  25.  
  26. CREATE TABLE IF NOT EXISTS `ly_role` (
  27. `id`
    smallint(6) unsigned NOT NULL AUTO_INCREMENT,
  28. `name`
    varchar(20) NOT NULL,
  29. `pid`
    smallint(6) DEFAULT NULL,
  30. `status`
    tinyint(1) unsigned DEFAULT NULL,
  31. `remark`
    varchar(255) DEFAULT NULL,
  32. PRIMARY KEY (`id`),
  33. KEY `pid`
    (`pid`),
  34. KEY `status` (`status`)
  35. ) ENGINE=MyISAM DEFAULT CHARSET=utf8 ;
  36.  
  37. CREATE TABLE IF NOT EXISTS `ly_role_user` (
  38. `role_id`
    mediumint(9) unsigned DEFAULT NULL,
  39. `user_id`
    char(32) DEFAULT NULL,
  40. KEY `group_id` (`role_id`),
  41. KEY `user_id` (`user_id`)
  42. ) ENGINE=MyISAM DEFAULT CHARSET=utf8;

下边对RBAC相关的数目库表及字段作一下介绍:

表名

字段名

字段类型

作用

ly_user

id

INT

用户ID(唯一识别号)

username

VARCHAR(16)

用户名

password

VARCHAR(32)

密码

email

VARCHAR(100)

用户邮箱

create_time

TIMESTAMP

始建时间(时间戳)

logintime

TIMESTAMP

新近两遍登录时间(时间戳)

loginip

VARCHAR(15)

日前报到的IP地址

status

TINYINT(1)

启用情形:0:表示禁用;1:表示启用

remark

VARCHAR(255)

备注新闻

ly_role

id

INT

角色ID

name

VARCHAR(20)

角色名称

pid

SMALLINT(6)

父角色对应ID

status

TINYINT(1)

启用意况(同上)

remark

VARCHAR(255)

备注音信

ly_node

id

SMALLINT(6)

节点ID

name

VARCHAR(20)

节点名称(英文名,对应使用控制器、应用、方法名)

title

VARCHAR(50)

节点粤语名(方便看懂)

status

TINYINT(1)

启用状况(同上)

remark

VARCHAR(255)

备考音信

sort

SMALLINT(6)

排序值(默认值为50)

pid

SMALLINT(6)

父节点ID(如:方法pid对应相应的控制器)

level

TINYINT(1)

节点类型:1:表示应用(模块);2:表示控制器;3:表示方法

ly_role_user

user_id

INT

用户ID

role_id

SMALLINT(6)

角色ID

ly_access

role_id

SMALLINT(6)

角色ID

node_id

SMALLINT(6)

节点ID

level

 

 

module

 

 

以下是数据库表各字段的关系关系:

ACCESS 2

兑现RBAC管理的前导性工作

基于ThinkPHP实现RBAC的权杖管理连串中,首先要做一些前导性的工作(系统数据库设计TP已经为我们成功了),紧要分以下多少个方面:

  • 用户(增、删、改、查)
  • 角色(增、删、改、查)
  • 节点(增、删、改、查)
  • 配备权力(更新权限)

切实实现的代码如下(相关解释均在诠释之中):

复制

  1. <?php
  2. /**
  3. * Created by PhpStorm.
  4. * User: LiuYang
  5. * Date: 14-9-6
  6. * Time: 下午9:54
  7. * Description:
    基于ThinkPHP实现的权位管理体系
  8. */
  9.  
  10. class RbacAction extends CommonAction {
  11.  
  12. //初叶化操作
  13. function
    _initialize(){
  14. if(!IS_AJAX) $this->error(‘你拜访的页面不设有,请稍后再试’);
  15. }
  16.  
  17.  
  18. //用户列表
  19. public function index(){
  20. $db = M(‘user’);
  21.  
  22. //当前页码
  23. $pageNum =
    I(‘post.pageNum’,1,’int’);
  24. //每页突显条数
  25. $numPerPage =
    I(‘post.numPerPage’,C(“numPerPage”),’int’);
  26. //总页码数
  27. $totalCount =
    $db->count();
  28.  
  29. $this->totalCount =
    $totalCount;
  30. $this->numPerPage =
    $numPerPage;
  31. $this->items = D(‘UserRelation’)->relation(true)->page($pageNum, $numPerPage)->select();
  32. $this->display();
  33. }
  34.  
  35. //添加编撰用户弹层表单
  36. public function addUser(){
  37. //假若设置了uid,则为编写用户,否则为扩张用户
  38. $this->role = M(‘role’)->where(‘status =
    1’)->field(‘id,name’)->select();
  39.  
  40. if(isset($_GET[‘uid’])) {
  41. $this->userinfo = M(‘user’)->where( “id = $_GET[uid]” )->find();
  42. }
  43. $this->display();
  44. }
  45.  
  46. //添加及编辑用户表单处理
  47. public function addUserHandler(){
  48.  
  49. $db = M(‘user’);
  50. if($_POST[‘id’]) {
  51. //如若存在ID,即意味着更新
  52. $data =
    array(
  53. ‘id’ => I(‘post.id’,”,’int’),
  54. ‘username’
    => I(‘username’, ”, ‘string’),
  55. ‘status’
    => I(‘status’,”, ‘int’),
  56. ‘remark’
    => I(‘remark’),
  57. ‘logintime’
    => time(),
  58. ‘loginip’
    => get_client_ip()
  59. );
  60.  
  61. if($_POST[‘password’])
    $data[‘password’] = I(‘password’,”, ‘md5’);
  62. if($db->save($data)) {
  63. $roleuser =
    M(‘role_user’);
  64.  
  65. $roleuser->where(“id =
    $data[id]”)->delete();
  66.  
  67. $roleuser->add(array(
  68. ‘role_id’
    => I(‘role’,”,’intval’),
  69. ‘user_id’
    => $data[id]
  70. ));
  71.  
  72. $this->ajaxReturn(array(
  73. ‘statusCode’
    => 200,
  74. ‘message’
    => ‘更新成功’
  75. ));
  76. } else {
  77. $this->ajaxReturn(array(
  78. ‘statusCode’
    => 300,
  79. ‘message’
    => ‘操作战败’
  80. ));
  81. }
  82.  
  83. return ;
  84. }
  85.  
  86. //添加表单处理
  87. $data =
    array(
  88. ‘username’
    => I(‘username’, ”, ‘string’),
  89. ‘password’
    => I(‘password’, ”, ‘md5’),
  90. ‘status’
    => I(‘status’,”, ‘int’),
  91. ‘remark’
    => I(‘remark’),
  92. ‘logintime’
    => time(),
  93. ‘loginip’
    => get_client_ip()
  94. );
  95. if($uid = M(‘user’)->add($data)) {
  96. $roleuser =
    M(‘role_user’);
  97.  
  98. $roleuser->where(“id =
    $uid”)->delete();
  99.  
  100. $roleuser->add(array(
  101. ‘role_id’
    => I(‘role’,”,’intval’),
  102. ‘user_id’
    =>
    $uid
  103. ));
  104.  
  105. $this->ajaxReturn(array(
  106. ‘statusCode’
    => 200,
  107. ‘message’
    => ‘操作成功’,
  108. ‘navTabId’
    => ”,
  109. ‘rel’ => ”,
  110. ‘callbackType’ => ”,
  111. ‘forwardUrl’
    => ”,
  112. ‘confirmMsg’
    => ”
  113. ));
  114. } else {
  115. $this->ajaxReturn(array(
  116. ‘statusCode’
    => 300,
  117. ‘message’
    => ‘操作失利’
  118. ));
  119. }
  120. }
  121.  
  122. //启用或楚用用户
  123. public function resume(){
  124. $id = I(‘get.id’,’0′,’int’);
  125. $db = M(‘user’);
  126. $status =
    $db->where(“id = $id”)->getField(‘status’);
  127. $status =
    ($status == 1)? 0 : 1 ;
  128. if($db->where(“id = $id”)->setField(‘status’,
    $status)){
  129. $this->ajaxReturn(array(
  130. ‘statusCode’
    => 1,
  131. ‘message’
    => ‘操作成功’,
  132. ‘navTabId’
    =>$_GET[‘navTabId’]
  133. ));
  134. } else {
  135. $this->ajaxReturn(array(
  136. ‘statusCode’
    => 0,
  137. ‘message’
    => ‘操作退步’
  138. ));
  139. }
  140. }
  141.  
  142. //删除用户
  143. public function deleteUserHandler(){
  144. $id = I(‘get.uid’,0,’int’);
  145. if( M(‘user’)->delete($id) ) {
  146. $this->ajaxReturn(array(
  147. ‘statusCode’
    => 1,
  148. ‘message’
    => ‘删除成功’,
  149. ‘navTabId’
    => $_GET[‘navTabId’]
  150. ));
  151. } else {
  152. $this->ajaxReturn(array(
  153. ‘statusCode’
    => 0,
  154. ‘message’
    => ‘删除成功’,
  155. ‘navTabId’
    => $_GET[‘navTabId’]
  156. ));
  157. }
  158. }
  159.  
  160. //节点列表
  161. public function node(){
  162. $node =
    M(‘node’)->where(array(‘status’=>1))->order(‘sort’)->select();
  163. $this->node =
    node_merge($node);
  164. $this->display();
  165. }
  166.  
  167. //添加及编辑节点弹层表单
  168. public function addNode(){
  169. //添加表单默认情况
  170. $this->info = array(
  171. ‘level’
    => I(‘get.level’,1,’int’),
  172. ‘pid’ => I(‘get.pid’,0,’int’),
  173. ‘status’
    => 1,
  174. ‘sort’ => 50
  175. );
  176. switch ($this->info[‘level’]){
  177. case 1: {
  178. $this->label = “应用”;
  179. break;
  180. }
  181. case 2: {
  182. $this->label = “控制器”;
  183. break;
  184. }
  185. case 3: {
  186. $this->label = “方法”;
  187. break;
  188. }
  189. }
  190. if($_GET[‘id’]) {
  191. //编辑形式
  192. $this->info = M(‘node’)->where(array(‘id’=>$_GET[‘id’]))->find();
  193. }
  194. $this->display();
  195. }
  196.  
  197. //添加及编辑节点表单处理
  198. public function addNodeHandler(){
  199. $id =
    $_POST[‘id’];
  200. $db = M(‘node’);
  201. if($id) {
  202. //更新
  203. if($db->save($_POST)) {
  204. $this->ajaxReturn(array(
  205. ‘statusCode’
    => 200,
  206. ‘message’
    => ‘添加事业有成’,
  207. ‘navTabId’
    => $_GET[‘navTabId’]
  208. ));
  209. } else {
  210. $this->ajaxReturn(array(
  211. ‘statusCode’
    => 300,
  212. ‘message’
    => ‘更新败北’,
  213. ‘navTabId’
    => $_GET[‘navTabId’]
  214. ));
  215. }
  216. }else {
  217. //保存
  218. if($db->add($_POST)) {
  219. $this->ajaxReturn(array(
  220. ‘statusCode’
    => 200,
  221. ‘message’
    => ‘添加事业有成’,
  222. ‘navTabId’
    => $_GET[‘navTabId’]
  223. ));
  224. } else {
  225. $this->ajaxReturn(array(
  226. ‘statusCode’
    => 300,
  227. ‘message’
    => ‘添加败北’,
  228. ‘navTabId’
    => $_GET[‘navTabId’]
  229. ));
  230. }
  231. }
  232. }
  233.  
  234. //删除节点
  235. public function deleteNodeHandler(){
  236. $id = I(‘get.id’,’0′,’int’);
  237. $db = M(‘node’);
  238. $data =
    $db->where(array(‘pid’=>$id))->field(‘id’)->find();
  239. if($data) {
  240. $this->ajaxReturn(array(
  241. ‘statusCode’
    => 0,
  242. ‘message’
    => ‘你请求删除的节点存在子节点,不可直接删除’
  243. ));
  244. } else {
  245. if($db->delete($id)) {
  246. $this->ajaxReturn(array(
  247. ‘statusCode’=> 1,
  248. ‘message’
    => ‘删除成功’
  249. ));
  250. } else {
  251. $this->ajaxReturn(array(
  252. ‘statusCode’
    => 0,
  253. ‘message’
    => ‘删除败北’
  254. ));
  255. }
  256. }
  257. //if($data[‘level’]
    === 3)
  258. }
  259.  
  260. //角色管理
  261. public function role(){
  262. $this->role = M(‘role’)->select();
  263. $this->display();
  264. }
  265.  
  266. //添加及编辑角色
  267. public function addRole(){
  268. if($_GET[‘rid’]) {
  269. $id = I(‘get.rid’,0,’int’);
  270. $this->role = M(‘role’)->find($id);
  271. }
  272. $this->display();
  273. }
  274.  
  275. //添加角色表单处理
  276. public function addRoleHandler(){
  277. $db = M(‘role’);
  278. if($_POST[‘id’]) {
  279. //更新
  280. if($db->save($_POST)) {
  281. $this->ajaxReturn(array(
  282. ‘statusCode’=> 200,
  283. ‘message’
    => “角色信息更新成功”
  284. ));
  285. } else {
  286. $this->ajaxReturn(array(
  287. ‘statusCode’
    => “300”,
  288. ‘message’
    => ‘角色信息更新退步’
  289. ));
  290. }
  291. } else {
  292. //添加表单处理
  293. if($db ->add($_POST)){
  294. $this->ajaxReturn(array(
  295. ‘statusCode’=> 200,
  296. ‘message’
    => “角色添加成功”
  297. ));
  298. }else {
  299. $this->ajaxReturn(array(
  300. ‘statusCode’
    => 300,
  301. ‘message’
    => ‘角色添加失利’
  302. ));
  303. }
  304. }
  305. }
  306.  
  307. //删除角色
  308. public function deleteRole(){
  309.  
  310. }
  311.  
  312. //快束启用或楚用用户
  313. public function resumeRole(){
  314. $id = I(‘get.rid’,0, ‘int’);
  315. $db = M(‘role’);
  316. $status =
    $db->where(“id = $id”)->getField(‘status’);
  317. $status =
    ($status == 1)? 0 : 1 ;
  318. if($db->where(“id = $id”)->setField(‘status’,
    $status)){
  319. $this->ajaxReturn(array(
  320. ‘statusCode’
    => 1,
  321. ‘message’
    => ‘操作成功’,
  322. ‘navTabId’
    =>$_GET[‘navTabId’]
  323. ));
  324. } else {
  325. $this->ajaxReturn(array(
  326. ‘statusCode’
    => 0,
  327. ‘message’
    => ‘操作败北’
  328. ));
  329. }
  330. }
  331.  
  332.  
  333. //给用户增长节点权限
  334. public function access(){
  335. $rid =
    I(‘rid’,0 ,’intval’);
  336. $node =
    M(‘node’)->where(array(‘status’=>1))->field(array(‘id’,’title’,’pid’,’name’,’level’))->order(‘sort’)->select();
  337.  
  338. //获取原有权限
  339. $access =
    M(‘access’)->where(“role_id = $rid”)->getField(‘node_id’,true);
  340. $this->node =
    node_merge($node,$access);
  341. $this->assign(‘rid’,$rid)->display();
  342. }
  343.  
  344. //添加节点权限表单处理
  345. public function accessHandler(){
  346. $rid =
    I(‘rid’, ”, ‘intval’);
  347. $db = M(‘access’);
  348. //清空原有权限
  349. $db->where(“role_id =
    $rid”)->delete();
  350.  
  351. //插入新的权柄
  352. $data =
    array();
  353.  
  354. foreach
    ($_POST[‘access’] as $v) {
  355. $tmp =
    explode(‘_’, $v);
  356. $data[]
    = array(
  357. ‘role_id’=> $rid,
  358. ‘node_id’=> $tmp[0],
  359. ‘level’=>$tmp[1]
  360. );
  361. }
  362. if($db->addAll($data)) {
  363. $this->ajaxReturn(array(
  364. ‘statusCode’=> 200,
  365. ‘message’
    => ‘权限更新成功’
  366. ));
  367. } else {
  368. $this->ajaxReturn(array(
  369. ‘statusCode’
    => 300,
  370. ‘message’
    => ‘权限更新失败’
  371. ));
  372. }
  373.  
  374. }
  375. }

ThinkPHP中RBAC类的详解

在ThinkPHP处理权限管理中,真正的难点并不是在RBAC类的应用上,下边相关的处理(权限配置,节点管理等);所以当成功以上工作,其实RBAC系统现已完结了90%。下边先从ThinkPHP中RBAC的布置说起(详细请参考对应的诠释内容):

复制

  1. <?php
  2. /**
  3. * Created by PhpStorm.
  4. * User: LiuYang
  5. * Date: 14-9-29
  6. * Time: 下午9:36
  7. * Description:
    ThinkPHP中RBAC处理类的部署文件
  8. */
  9.  
  10. return array(
  11.  
  12. “USER_AUTH_ON” => true, //是否打开权限验证(必配)
  13. “USER_AUTH_TYPE” => 1, //验证格局(1、登录验证;2、实时验证)
  14.  
  15. “USER_AUTH_KEY” => ‘uid’, //用户认证识别号(必配)
  16. “ADMIN_AUTH_KEY” => ‘superadmin’, //一级管理员识别号(必配)
  17. “USER_AUTH_MODEL” => ‘user’, //验证用户表模型
    ly_user
  18. ‘USER_AUTH_GATEWAY’ => ‘/Public/login’,
    //用户认证败北,跳转URL
  19.  
  20. ‘AUTH_PWD_ENCODER’=>’md5’, //默认密码加密方法
  21.  
  22. “RBAC_SUPERADMIN” => ‘admin’, //顶级管理员名称
  23.  
  24.  
  25. “NOT_AUTH_MODULE” => ‘Index,Public’,
    //无需认证的控制器
  26. “NOT_AUTH_ACTION” => ‘index’, //无需认证的办法
  27.  
  28. ‘REQUIRE_AUTH_MODULE’ => ”, //默认需要证实的模块
  29. ‘REQUIRE_AUTH_ACTION’ => ”, //默认需要表明的动作
  30.  
  31. ‘GUEST_AUTH_ON’ => false, //是否开启游客授权访问
  32. ‘GUEST_AUTH_ID’ => 0, //游客标记
  33.  
  34. “RBAC_ROLE_TABLE” => ‘ly_role’, //角色表名称(必配)
  35. “RBAC_USER_TABLE” => ‘ly_role_user’,
    //用户角色中间表名称(必配)
  36. “RBAC_ACCESS_TABLE” => ‘ly_access’, //权限表名称(必配)
  37. “RBAC_NODE_TABLE” => ‘ly_node’, //节点表名称(必配)
  38. );

注意:

  • 以上部分配置项并非必须的,但标有“必配”,则必须配备
  • 不要验证的权限和艺术与需要表达的模块和动作可以依照需要拔取性配置,还有一对权力相关部署并未列表出

RBAC处理类提供静态的主意

ThinkPHP的RBAC处理类提供给我们很多有关的静态方法如下:

方法名 接收参数说明 返回值 说明
RBAC::authenticate($map,$model=”);
  • $map:ThinkPHP数据库处理类的where条件参数
  • $model:用户表名,默认取配置文件C('USER_AUTH_MODEL')
array

RBAC::authenticate(array("username"=>"admin","userpwd" => I('POST.pwd','', 'md5')));

返回值是在用户表中,以$map为条件where的查阅结果集

0RBAC::saveAccessList($authId=null);
  • $authId:用户识别号,默认取C('USER_AUTH_KEY');
返回一个空值 如果验证方式为登录验证,则将权限写入session中,否则不作任何处理
RBAC::getRecordAccessList($authId=null,$module=”);
  • $authId:用户识别号(可不传)
  • $module:当前操作的模块名称
Array 返回一个包含权限的ID的数组
RBAC::checkAccess() 返回true或false 检查当前操作是否需要认证(根据配置中需要认证和不需要评论的模块或方法得出)
RBAC::checkLogin() true 如果当前操作需要认证且用户没有登录,继续检测是否开启游客授权。如果开启游客授权,则写入游客权限;否则跳到登录页
RBAC::AccessDecision($appName=APP_NAME)
  • $appName:选传,有默认值
  • true:表示有操作权限
  • false:无操作权限
AccessDecision($appName=APP_NAME)方法,检测当前项目模块操作,是否存在于$_SESSION[‘_ACCESS_LIST’]数组中$_SESSION[‘_ACCESS_LIST’][‘当前操作’][‘当前模块’][‘当前操作’]是否存在。如果存在表示有权限,返回true;否则返回flase。
RBAC::getAccessList($authId)
  • $authId:用户识别号(选传,程序自动获取)
Array 通过数据库查询取得当前认证号的所有权限列表
RBAC::getModuleAccessList($authId,$module)
  • $authId:用户识别号(必)
  • $module:对应的模块(必)
Array 返回指定用户可访问的节点权限数组

注意:在使用RBAC::AccessDecision()办法时,如若您敞开了项目分组,则必须传入当前分组,代码如下:

复制

  1. //权限验证
  2. if(C(‘USER_AUTH_ON’) && !$notAuth) {
  3. import(‘ORG.Util.RBAC’);
  4. //使用了连串分组,则必须引入GROUP_NAME
  5. RBAC::AccessDecision(GROUP_NAME) || $this->error(“你从未对号入座的权位”);
  6. }

RBAC处理类的骨子里运用

在形成用户登录,角色创设,节点增删改查的办事后,就只剩下了RBAC怎样在相应程序代码中采取了。挻简单的,只用在原先的代码其他上改变多少个地点即可。

  • 用户登录时,写入用户权限
  • 用户操作时,举行权力验证

下边是用户登录时的实现代码:

复制

  1. >?php
  2. /**
  3. * Created by PhpStorm.
  4. * User: LiuYang
  5. * Date: 14-8-24
  6. * Time: 下午5:23
  7. * Description: 用户登户及退出控制器
  8. */
  9.  
  10. class LoginAction extends Action {
  11.  
  12. //用户登录视图
  13. public function index(){
  14. //…
  15. }
  16.  
  17. //用户登录处理表单
  18. public function loginHandle(){
  19. if(!IS_POST) halt(‘页面不存在,请稍后再试’);
  20. if(session(‘verify’) != I(‘param.verify’,”,’md5′)) {
  21. $this->error(‘验证码错误’, U(‘Admin/Login/index’));
  22. }
  23.  
  24. $user =
    I(‘username’,”,’string’);
  25. $passwd =
    I(‘password’,”,’md5′);
  26.  
  27. $db = M(‘user’);
  28. $userinfo =
    $db->where(“username = ‘$user’ AND password =
    ‘$passwd'”)->find();
  29.  
  30. if(!$userinfo)
    $this->error(‘用户名或密码错误’, U(‘Admin/Login/index’));
  31.  
  32. if(!$userinfo[‘status’])
    $this->error(‘该用户被锁定,暂时不可登录’, U(‘Admin/Login/index’));
  33.  
  34. //更新登录音讯
  35. $db->save(array(“id”=> $userinfo[“id”], “logintime”=>
    time(), “loginip” => get_client_ip()));
  36.  
  37. //写入session值
  38. session(C(“USER_AUTH_KEY”),
    $userinfo[“id”]);
  39. session(“username”,
    $userinfo[“username”]);
  40. session(“logintime”,
    $userinfo[“logintime”]);
  41. session(“loginip”,$user[“loginip”]);
  42.  
  43. //假设为最佳管理员,则无需验证
  44. if($userinfo[‘username’] == C(‘RBAC_SUPERADMIN’))
    {
  45. session(C(‘ADMIN_AUTH_KEY’),
    true);
  46. }
  47.  
  48. //载入RBAC类
  49. import(‘ORG.Util.RBAC’);
  50. //读取用户权限
  51. RBAC::saveAccessList();
  52.  
  53. $this->success(‘登录成功’, U(‘Admin/Index/index’));
  54. }
  55.  
  56. //登出登录
  57. public function logOut(){
  58. //…
  59. }
  60.  
  61. //验证码
  62. public function verify(){
  63. //…
  64. }
  65. }

随后在控制器目录创设一个CommonAction.class.php文本,然后改写所有要权限验证的类,让其后续自CommonAction。代码如下:

复制

  1. <?php
  2. /**
  3. * Created by PhpStorm.
  4. * User: LiuYang
  5. * Date: 14-9-3
  6. * Time: 下午8:40
  7. * Description: 操作权限验证
  8. */
  9.  
  10. class CommonAction extends Action {
  11. function
    _initialize(){
  12. if(!isset($_SESSION[C(‘USER_AUTH_KEY’)])) {
  13. $this->redirect(‘Admin/Login/index’);
  14. }
  15.  
  16. $notAuth =
    in_array(MODULE_NAME, explode(‘,’, C(‘NOT_AUTH_MODULE’))) || in_array(ACTION_NAME, C(‘NOT_AUTH_ACTION’));
  17.  
  18. //权限验证
  19. if(C(‘USER_AUTH_ON’)
    && !$notAuth) {
  20. import(‘ORG.Util.RBAC’);
  21. //使用了档次分组,则必须引入GROUP_NAME
  22. RBAC::AccessDecision(GROUP_NAME) || $this->error(“你从未对号入座的权能”);
  23. }
  24. }
  25. }

ThinkPHP中提供了一个_initialize()形式,是在类开始化就会执行的,也就是一旦前面控制器继承自CommonAction类,就会在作相应操作时,执行_initialize()方法。

本文以上实例代码及有关源码下载:

下载EER图 下载源码

人无完人,肯定有不足之处,望拍砖指导(本文完)。

相关文章