AuthService.php 6.9 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176
  1. <?php
  2. // +----------------------------------------------------------------------
  3. // | framework
  4. // +----------------------------------------------------------------------
  5. // | 版权所有 2014~2018 广州楚才信息科技有限公司 [ http://www.cuci.cc ]
  6. // +----------------------------------------------------------------------
  7. // | 官方网站: http://framework.thinkadmin.top
  8. // +----------------------------------------------------------------------
  9. // | 开源协议 ( https://mit-license.org )
  10. // +----------------------------------------------------------------------
  11. // | github开源项目:https://github.com/zoujingli/framework
  12. // +----------------------------------------------------------------------
  13. namespace app\admin\service;
  14. use library\tools\Data;
  15. use library\tools\Node;
  16. use think\Db;
  17. /**
  18. * 权限访问及菜单管理
  19. * Class AuthService
  20. * @package app\admin\service
  21. */
  22. class AuthService
  23. {
  24. /**
  25. * 权限节点忽略规则
  26. * @return array
  27. */
  28. public static function getIgnore()
  29. {
  30. return ['index', 'admin/login', 'admin/index'];
  31. }
  32. /**
  33. * 获取系统代码节点
  34. * @param array $nodes
  35. * @return array
  36. * @throws \ReflectionException
  37. */
  38. public static function get($nodes = [])
  39. {
  40. list($ignore, $map) = [self::getIgnore(), Node::getClassTreeNode(env('app_path'))];
  41. $alias = Db::name('SystemNode')->column('node,is_menu,is_auth,is_login,title');
  42. foreach (Node::getMethodTreeNode(env('app_path')) as $thr => $title) {
  43. foreach ($ignore as $str) if (stripos($thr, $str) === 0) continue 2;
  44. $tmp = explode('/', $thr);
  45. list($one, $two) = ["{$tmp[0]}", "{$tmp[0]}/{$tmp[1]}"];
  46. $nodes[$one] = array_merge(isset($alias[$one]) ? $alias[$one] : ['node' => $one, 'title' => '', 'is_menu' => 0, 'is_auth' => 0, 'is_login' => 0], ['pnode' => '']);
  47. $nodes[$two] = array_merge(isset($alias[$two]) ? $alias[$two] : ['node' => $two, 'title' => isset($map[$two]) ? $map[$two] : '', 'is_menu' => 0, 'is_auth' => 0, 'is_login' => 0], ['pnode' => $one]);
  48. $nodes[$thr] = array_merge(isset($alias[$thr]) ? $alias[$thr] : ['node' => $thr, 'title' => $title, 'is_menu' => 0, 'is_auth' => 0, 'is_login' => 0], ['pnode' => $two]);
  49. }
  50. foreach ($nodes as &$node) list($node['is_auth'], $node['is_menu'], $node['is_login']) = [intval($node['is_auth']), intval($node['is_menu']), empty($node['is_auth']) ? intval($node['is_login']) : 1];
  51. return $nodes;
  52. }
  53. /**
  54. * 检查用户节点权限
  55. * @param string $node 节点
  56. * @return boolean
  57. */
  58. public static function checkAuthNode($node)
  59. {
  60. list($module, $controller, $action) = explode('/', str_replace(['?', '=', '&'], '/', "{$node}///"));
  61. $current = Node::parseString("{$module}/{$controller}") . strtolower("/{$action}");
  62. // 后台入口无需要验证权限
  63. if (stripos($node, 'admin/index') === 0) return true;
  64. // 超级管理员无需要验证权限
  65. if (session('user.username') === 'admin') return true;
  66. // 未配置权限的节点默认放行
  67. if (!in_array($current, self::getAuthNode())) return true;
  68. // 用户指定角色授权放行
  69. return in_array($current, (array)session('user.nodes'));
  70. }
  71. /**
  72. * 获取授权节点
  73. * @return array
  74. */
  75. public static function getAuthNode()
  76. {
  77. $nodes = cache('need_access_node');
  78. if (empty($nodes)) {
  79. $nodes = Db::name('SystemNode')->where(['is_auth' => '1'])->column('node');
  80. cache('need_access_node', $nodes);
  81. }
  82. return $nodes;
  83. }
  84. /**
  85. * 应用用户权限节点
  86. * @return boolean
  87. * @throws \think\db\exception\DataNotFoundException
  88. * @throws \think\db\exception\ModelNotFoundException
  89. * @throws \think\exception\DbException
  90. */
  91. public static function applyNode()
  92. {
  93. cache('need_access_node', null);
  94. if (($uid = session('user.id'))) session('user', Db::name('SystemUser')->where('id', $uid)->find());
  95. if (session('user.authorize') && ($ids = explode(',', session('user.authorize')))) {
  96. $auths = Db::name('SystemAuth')->whereIn('id', $ids)->where('status', '1')->column('id');
  97. if (empty($auths)) return session('user.nodes', []);
  98. return session('user.nodes', Db::name('SystemAuthNode')->whereIn('auth', $auths)->column('node'));
  99. }
  100. return false;
  101. }
  102. /**
  103. * 判断用户登录状态
  104. * @return boolean
  105. */
  106. public static function isLogin()
  107. {
  108. return !!session('user');
  109. }
  110. /**
  111. * 获取授权后的菜单
  112. * @return array
  113. * @throws \ReflectionException
  114. * @throws \think\db\exception\DataNotFoundException
  115. * @throws \think\db\exception\ModelNotFoundException
  116. * @throws \think\exception\DbException
  117. */
  118. public static function getAuthMenu()
  119. {
  120. self::applyNode();
  121. $list = Db::name('SystemMenu')->where('status', '1')->order('sort asc,id asc')->select();
  122. return self::buildMenuData(Data::arr2tree($list), self::get(), self::isLogin());
  123. }
  124. /**
  125. * 后台主菜单权限过滤
  126. * @param array $menus 当前菜单列表
  127. * @param array $nodes 系统权限节点数据
  128. * @param bool $isLogin 是否已经登录
  129. * @return array
  130. */
  131. private static function buildMenuData($menus, $nodes, $isLogin)
  132. {
  133. foreach ($menus as $key => &$menu) {
  134. if (!empty($menu['sub'])) $menu['sub'] = self::buildMenuData($menu['sub'], $nodes, $isLogin);
  135. if (!empty($menu['sub'])) $menu['url'] = '#';
  136. elseif (preg_match('/^https?\:/i', $menu['url'])) continue;
  137. elseif ($menu['url'] !== '#') {
  138. $node = join('/', array_slice(explode('/', preg_replace('/[\W]/', '/', $menu['url'])), 0, 3));
  139. $menu['url'] = url($menu['url']) . (empty($menu['params']) ? '' : "?{$menu['params']}");
  140. if (isset($nodes[$node]) && $nodes[$node]['is_login'] && empty($isLogin)) unset($menus[$key]);
  141. elseif (isset($nodes[$node]) && $nodes[$node]['is_auth'] && $isLogin && !self::checkAuthNode($node)) unset($menus[$key]);
  142. } else unset($menus[$key]);
  143. }
  144. return $menus;
  145. }
  146. /**
  147. * 检查密码是否合法
  148. * @param string $password
  149. * @return array
  150. */
  151. public static function checkPassword($password)
  152. {
  153. $password = trim($password);
  154. if (!strlen($password) >= 6) {
  155. return ['code' => 0, 'msg' => '密码必须大于6字符!'];
  156. }
  157. if (!preg_match("/^(?![\d]+$)(?![a-zA-Z]+$)(?![^\da-zA-Z]+$).{6,32}$/", $password)) {
  158. return ['code' => 0, 'msg' => '密码必需包含大小写字母、数字、符号任意两者组合!'];
  159. }
  160. return ['code' => 1, 'msg' => '密码复杂度通过验证!'];
  161. }
  162. }