Auth.php 6.3 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192
  1. <?php
  2. /**
  3. * Auth权限验证类
  4. */
  5. namespace auth;
  6. use think\Db;
  7. use think\facade\Session;
  8. use think\facade\Config;
  9. class Auth
  10. {
  11. protected $_config = [
  12. 'auth_on' => true, // 认证开关
  13. 'auth_type' => 1, // 认证方式,1为实时认证;2为登录认证。
  14. 'auth_group' => 'role', // 权限组数据表名
  15. 'auth_rule' => 'rule', // 权限规则表
  16. 'auth_user' => 'admin', // 管理员信息表
  17. 'auth_user_id_field'=> 'id', // 管理员表ID字段名
  18. ];
  19. public function __construct()
  20. {
  21. if (Config::pull('auth')) {
  22. $this->_config = array_merge($this->_config, Config::pull('auth'));
  23. }
  24. }
  25. /**
  26. * 检查权限
  27. * @param string|array $name 需要验证的规则列表,支持逗号分隔的权限规则或索引数组
  28. * @param integer $uid 认证用户ID
  29. * @param string $relation 如果为 'or' 表示满足任一条规则即通过验证;如果为 'and' 则表示需满足所有规则才能通过验证
  30. * @param string $mode 执行check的模式
  31. * @param integer $type 规则类型
  32. * @return boolean 通过验证返回true;失败返回false
  33. */
  34. public function check($name, $uid, $relation = 'or', $mode = 'url', $type = 1)
  35. {
  36. if (!$this->_config['auth_on']) {
  37. return true;
  38. }
  39. $authList = $this->getAuthList($uid, $type);
  40. if (is_string($name)) {
  41. $name = strtolower($name);
  42. if (strpos($name, ',') !== false) {
  43. $name = explode(',', $name);
  44. } else {
  45. $name = [$name];
  46. }
  47. }
  48. $list = [];
  49. if ($mode === 'url') {
  50. $REQUEST = unserialize(strtolower(serialize($_REQUEST)));
  51. }
  52. foreach ($authList as $auth) {
  53. $query = preg_replace('/^.+\?/U', '', $auth);
  54. if ($mode === 'url' && $query != $auth) {
  55. parse_str($query, $param); // 解析规则中的param
  56. $intersect = array_intersect_assoc($REQUEST, $param);
  57. $auth = preg_replace('/\?.*$/U', '', $auth);
  58. if (in_array($auth, $name) && $intersect == $param) {
  59. $list[] = $auth;
  60. }
  61. } elseif (in_array($auth, $name)) {
  62. $list[] = $auth;
  63. }
  64. }
  65. if ($relation === 'or' && !empty($list)) {
  66. return true;
  67. }
  68. $diff = array_diff($name, $list);
  69. if ($relation === 'and' && empty($diff)) {
  70. return true;
  71. }
  72. return false;
  73. }
  74. /**
  75. * 根据用户ID获取用户组,返回值为数组
  76. * @param integer $uid 用户ID
  77. * @return array 用户所属用户组 ['uid'=>'用户ID', 'rid'=>'用户组ID', 'name'=>'用户组名', 'jurisdiction'=>'用户组拥有的规则ID,多个用英文,隔开']
  78. */
  79. public function getGroups($uid)
  80. {
  81. static $groups = [];
  82. if (isset($groups[$uid])) {
  83. return $groups[$uid];
  84. }
  85. /*$user_groups = Db::name($this->_config['auth_group_access'])
  86. ->alias('a')
  87. ->where('a.uid', $uid)
  88. ->where('g.status', 1)
  89. ->join($this->_config['auth_group'].' g', "a.group_id = g.id")
  90. ->field('uid,group_id,name,rules')
  91. ->select();*/
  92. $user_groups = Db::name($this->_config['auth_user'])
  93. ->alias('a')
  94. ->where('a.id',$uid)
  95. ->join($this->_config['auth_group'].' g',"a.roles=g.id")
  96. ->where('g.status',1)
  97. ->field('a.id as uid,g.id as rid,jurisdiction')
  98. ->select();
  99. $groups[$uid] = $user_groups ?: [];
  100. return $groups[$uid];
  101. }
  102. /**
  103. * 获得权限列表
  104. * @param integer $uid 用户ID
  105. * @param integer $type 规则类型
  106. * @return array 权限列表
  107. */
  108. protected function getAuthList($uid, $type)
  109. {
  110. static $_authList = [];
  111. $t = implode(',', (array)$type);
  112. if (isset($_authList[$uid.$t])) {
  113. return $_authList[$uid.$t];
  114. }
  115. if ($this->_config['auth_type'] == 2 && Session::has('_AUTH_LIST_'.$uid.$t)) {
  116. return Session::get('_AUTH_LIST_'.$uid.$t);
  117. }
  118. // 读取用户所属用户组
  119. $groups = $this->getGroups($uid);
  120. $ids = []; // 保存用户所属用户组设置的所有权限规则ID
  121. foreach ($groups as $g) {
  122. $ids = array_merge($ids, explode(',', trim($g['jurisdiction'], ',')));
  123. }
  124. $ids = array_unique($ids);
  125. if (empty($ids)) {
  126. $_authList[$uid.$t] = [];
  127. return [];
  128. }
  129. $map = [
  130. ['id', 'in', $ids],
  131. ['type', '=', $type],
  132. ['status', '=', 1],
  133. ['level', '=', 2],
  134. ];
  135. // 读取用户组所有权限规则
  136. $rules = Db::name($this->_config['auth_rule'])->where($map)->field('condition,href')->select();
  137. // 循环规则,判断结果。
  138. $authList = [];
  139. foreach ($rules as $rule) {
  140. if (!empty($rule['condition'])) { // 根据condition进行验证
  141. $user = $this->getUserInfo($uid); // 获取用户信息,一维数组
  142. $command = preg_replace('/\{(\w*?)\}/', '$user[\'\\1\']', $rule['condition']);
  143. // dump($command); // debug
  144. @(eval('$condition=('.$command.');'));
  145. if ($condition) {
  146. $authList[] = strtolower($rule['href']);
  147. }
  148. } else {
  149. // 只要存在就记录
  150. $authList[] = strtolower($rule['href']);
  151. }
  152. }
  153. $_authList[$uid.$t] = $authList;
  154. if ($this->_config['auth_type'] == 2) {
  155. Session::set('_AUTH_LIST_'.$uid.$t, $authList);
  156. }
  157. return array_unique($authList);
  158. }
  159. /**
  160. * 获得用户资料,根据自己的情况读取数据库
  161. */
  162. protected function getUserInfo($uid) {
  163. static $userinfo = [];
  164. if (!isset($userinfo[$uid])) {
  165. $userinfo[$uid] = Db::name($this->_config['auth_user'])->where((string)$this->_config['auth_user_id_field'], $uid)->find();
  166. }
  167. return $userinfo[$uid];
  168. }
  169. }