Auth.class.php 7.6 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186
  1. <?php
  2. // +----------------------------------------------------------------------
  3. // | ThinkPHP [ WE CAN DO IT JUST THINK IT ]
  4. // +----------------------------------------------------------------------
  5. // | Copyright (c) 2011 http://thinkphp.cn All rights reserved.
  6. // +----------------------------------------------------------------------
  7. // | Licensed ( http://www.apache.org/licenses/LICENSE-2.0 )
  8. // +----------------------------------------------------------------------
  9. // | Author: luofei614 <weibo.com/luofei614> 
  10. // +----------------------------------------------------------------------
  11. /**
  12. * 权限认证类
  13. * 功能特性:
  14. * 1,是对规则进行认证,不是对节点进行认证。用户可以把节点当作规则名称实现对节点进行认证。
  15. * $auth=new Auth(); $auth->check('规则名称','用户id')
  16. * 2,可以同时对多条规则进行认证,并设置多条规则的关系(or或者and)
  17. * $auth=new Auth(); $auth->check('规则1,规则2','用户id','and')
  18. * 第三个参数为and时表示,用户需要同时具有规则1和规则2的权限。 当第三个参数为or时,表示用户值需要具备其中一个条件即可。默认为or
  19. * 3,一个用户可以属于多个用户组(think_auth_group_access表 定义了用户所属用户组)。我们需要设置每个用户组拥有哪些规则(think_auth_group 定义了用户组权限)
  20. *
  21. * 4,支持规则表达式。
  22. * 在think_auth_rule 表中定义一条规则时,如果type为1, condition字段就可以定义规则表达式。 如定义{score}>5 and {score}<100 表示用户的分数在5-100之间时这条规则才会通过。
  23. * @category ORG
  24. * @package ORG
  25. * @subpackage Util
  26. * @author luofei614<weibo.com/luofei614>
  27. */
  28. //数据库
  29. /*
  30. -- ----------------------------
  31. -- think_auth_rule,规则表,
  32. -- id:主键,name:规则唯一标识, title:规则中文名称 status 状态:为1正常,为0禁用,condition:规则表达式,为空表示存在就验证,不为空表示按照条件验证
  33. -- ----------------------------
  34. DROP TABLE IF EXISTS `think_auth_rule`;
  35. CREATE TABLE `think_auth_rule` (
  36. `id` mediumint(8) unsigned NOT NULL AUTO_INCREMENT,
  37. `name` char(80) NOT NULL DEFAULT '',
  38. `title` char(20) NOT NULL DEFAULT '',
  39. `status` tinyint(1) NOT NULL DEFAULT '1',
  40. `condition` char(100) NOT NULL DEFAULT '',
  41. PRIMARY KEY (`id`),
  42. UNIQUE KEY `name` (`name`)
  43. ) ENGINE=MyISAM DEFAULT CHARSET=utf8;
  44. -- ----------------------------
  45. -- think_auth_group 用户组表,
  46. -- id:主键, title:用户组中文名称, rules:用户组拥有的规则id, 多个规则","隔开,status 状态:为1正常,为0禁用
  47. -- ----------------------------
  48. DROP TABLE IF EXISTS `think_auth_group`;
  49. CREATE TABLE `think_auth_group` (
  50. `id` mediumint(8) unsigned NOT NULL AUTO_INCREMENT,
  51. `title` char(100) NOT NULL DEFAULT '',
  52. `status` tinyint(1) NOT NULL DEFAULT '1',
  53. `rules` char(80) NOT NULL DEFAULT '',
  54. PRIMARY KEY (`id`)
  55. ) ENGINE=MyISAM DEFAULT CHARSET=utf8;
  56. -- ----------------------------
  57. -- think_auth_group_access 用户组明细表
  58. -- uid:用户id,group_id:用户组id
  59. -- ----------------------------
  60. DROP TABLE IF EXISTS `think_auth_group_access`;
  61. CREATE TABLE `think_auth_group_access` (
  62. `uid` mediumint(8) unsigned NOT NULL,
  63. `group_id` mediumint(8) unsigned NOT NULL,
  64. UNIQUE KEY `uid_group_id` (`uid`,`group_id`),
  65. KEY `uid` (`uid`),
  66. KEY `group_id` (`group_id`)
  67. ) ENGINE=MyISAM DEFAULT CHARSET=utf8;
  68. */
  69. class Auth{
  70. //默认配置
  71. protected $_config = array(
  72. 'AUTH_ON' => true, //认证开关
  73. 'AUTH_TYPE' => 1, // 认证方式,1为时时认证;2为登录认证。
  74. 'AUTH_GROUP' => 'think_auth_group', //用户组数据表名
  75. 'AUTH_GROUP_ACCESS' => 'think_auth_group_access', //用户组明细表
  76. 'AUTH_RULE' => 'think_auth_rule', //权限规则表
  77. 'AUTH_USER' => 'think_members'//用户信息表
  78. );
  79. public function __construct() {
  80. if (C('AUTH_CONFIG')) {
  81. //可设置配置项 AUTH_CONFIG, 此配置项为数组。
  82. $this->_config = array_merge($this->_config, C('AUTH_CONFIG'));
  83. }
  84. }
  85. //获得权限$name 可以是字符串或数组或逗号分割, uid为 认证的用户id, $or 是否为or关系,为true是, name为数组,只要数组中有一个条件通过则通过,如果为false需要全部条件通过。
  86. public function check($name, $uid, $relation='or') {
  87. if (!$this->_config['AUTH_ON'])
  88. return true;
  89. $authList = $this->getAuthList($uid);
  90. if (is_string($name)) {
  91. if (strpos($name, ',') !== false) {
  92. $name = explode(',', $name);
  93. } else {
  94. $name = array($name);
  95. }
  96. }
  97. $list = array(); //有权限的name
  98. foreach ($authList as $val) {
  99. if (in_array($val, $name))
  100. $list[] = $val;
  101. }
  102. if ($relation=='or' and !empty($list)) {
  103. return true;
  104. }
  105. $diff = array_diff($name, $list);
  106. if ($relation=='and' and empty($diff)) {
  107. return true;
  108. }
  109. return false;
  110. }
  111. //获得用户组,外部也可以调用
  112. public function getGroups($uid) {
  113. static $groups = array();
  114. if (isset($groups[$uid]))
  115. return $groups[$uid];
  116. $user_groups = M()->table($this->_config['AUTH_GROUP_ACCESS'] . ' a')->where("a.uid='$uid' and g.status='1'")->join($this->_config['AUTH_GROUP']." g on a.group_id=g.id")->select();
  117. $groups[$uid]=$user_groups?$user_groups:array();
  118. return $groups[$uid];
  119. }
  120. //获得权限列表
  121. protected function getAuthList($uid) {
  122. static $_authList = array();
  123. if (isset($_authList[$uid])) {
  124. return $_authList[$uid];
  125. }
  126. if(isset($_SESSION['_AUTH_LIST_'.$uid])){
  127. return $_SESSION['_AUTH_LIST_'.$uid];
  128. }
  129. //读取用户所属用户组
  130. $groups = $this->getGroups($uid);
  131. $ids = array();
  132. foreach ($groups as $g) {
  133. $ids = array_merge($ids, explode(',', trim($g['rules'], ',')));
  134. }
  135. $ids = array_unique($ids);
  136. if (empty($ids)) {
  137. $_authList[$uid] = array();
  138. return array();
  139. }
  140. //读取用户组所有权限规则
  141. $map=array(
  142. 'id'=>array('in',$ids),
  143. 'status'=>1
  144. );
  145. $rules = M()->table($this->_config['AUTH_RULE'])->where($map)->select();
  146. //循环规则,判断结果。
  147. $authList = array();
  148. foreach ($rules as $r) {
  149. if (!empty($r['condition'])) {
  150. //条件验证
  151. $user = $this->getUserInfo($uid);
  152. $command = preg_replace('/\{(\w*?)\}/', '$user[\'\\1\']', $r['condition']);
  153. //dump($command);//debug
  154. @(eval('$condition=(' . $command . ');'));
  155. if ($condition) {
  156. $authList[] = $r['name'];
  157. }
  158. } else {
  159. //存在就通过
  160. $authList[] = $r['name'];
  161. }
  162. }
  163. $_authList[$uid] = $authList;
  164. if($this->_config['AUTH_TYPE']==2){
  165. //session结果
  166. $_SESSION['_AUTH_LIST_'.$uid]=$authList;
  167. }
  168. return $authList;
  169. }
  170. //获得用户资料,根据自己的情况读取数据库
  171. protected function getUserInfo($uid) {
  172. static $userinfo=array();
  173. if(!isset($userinfo[$uid])){
  174. $userinfo[$uid]=M()->table($this->_config['AUTH_USER'])->find($uid);
  175. }
  176. return $userinfo[$uid];
  177. }
  178. }