AuthService.php 6.7 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232
  1. <?php
  2. namespace app\common\service;
  3. use app\admin\service\annotation\NodeAnnotation;
  4. use app\common\constants\AdminConstant;
  5. use think\facade\Db;
  6. /**
  7. * 权限验证服务
  8. * Class AuthService
  9. * @package app\common\service
  10. */
  11. class AuthService
  12. {
  13. /**
  14. * 用户ID
  15. * @var null
  16. */
  17. protected $adminId = null;
  18. /**
  19. * 默认配置
  20. * @var array
  21. */
  22. protected $config = [
  23. 'auth_on' => true, // 权限开关
  24. 'system_admin' => 'system_admin', // 用户表
  25. 'system_auth' => 'system_auth', // 权限表
  26. 'system_node' => 'system_node', // 节点表
  27. 'system_auth_node' => 'system_auth_node',// 权限-节点表
  28. ];
  29. /**
  30. * 管理员信息
  31. * @var array|\think\Model|null
  32. */
  33. protected $adminInfo;
  34. /**
  35. * 所有节点信息
  36. * @var array
  37. */
  38. protected $nodeList;
  39. /**
  40. * 管理员所有授权节点
  41. * @var array
  42. */
  43. protected $adminNode;
  44. /***
  45. * 构造方法
  46. * AuthService constructor.
  47. * @param null $adminId
  48. * @throws \think\db\exception\DataNotFoundException
  49. * @throws \think\db\exception\DbException
  50. * @throws \think\db\exception\ModelNotFoundException
  51. */
  52. public function __construct($adminId = null)
  53. {
  54. $this->adminId = $adminId;
  55. $this->adminInfo = $this->getAdminInfo();
  56. $this->nodeList = $this->getNodeList();
  57. $this->adminNode = $this->getAdminNode();
  58. return $this;
  59. }
  60. /**
  61. * 检测检测权限
  62. * @param null $node
  63. * @return bool
  64. * @throws \think\db\exception\DataNotFoundException
  65. * @throws \think\db\exception\DbException
  66. * @throws \think\db\exception\ModelNotFoundException
  67. */
  68. public function checkNode($node = null)
  69. {
  70. // 判断是否为超级管理员
  71. if ($this->adminId == AdminConstant::SUPER_ADMIN_ID) {
  72. return true;
  73. }
  74. // 判断权限验证开关
  75. if ($this->config['auth_on'] == false) {
  76. return true;
  77. }
  78. // 验证是否为URL
  79. if (filter_var($node, FILTER_VALIDATE_URL)) {
  80. return true;
  81. }
  82. // 判断是否需要获取当前节点
  83. if (empty($node)) {
  84. $node = $this->getCurrentNode();
  85. }else {
  86. $node = $this->parseNodeStr($node);
  87. }
  88. // 判断是否加入节点控制,优先获取缓存信息
  89. if (!isset($this->nodeList[$node])) {
  90. return false;
  91. }
  92. $nodeInfo = $this->nodeList[$node];
  93. if ($nodeInfo['is_auth'] == 0) {
  94. return true;
  95. }
  96. // 用户验证,优先获取缓存信息
  97. if (empty($this->adminInfo) || $this->adminInfo['status'] != 1 || empty($this->adminInfo['auth_ids'])) {
  98. return false;
  99. }
  100. // 判断该节点是否允许访问
  101. if (in_array($node, $this->adminNode)) {
  102. return true;
  103. }
  104. if ($this->checkNodeAnnotationAttrAuth($node)) return true;
  105. return false;
  106. }
  107. protected function checkNodeAnnotationAttrAuth(string $node): bool
  108. {
  109. $bool = false;
  110. $controller = request()->controller();
  111. try {
  112. $controllerExplode = explode('.', $controller);
  113. [$_name, $_controller] = $controllerExplode;
  114. $nodeExplode = explode('/', $node);
  115. $action = end($nodeExplode);
  116. $reflectionClass = new \ReflectionClass("app\admin\controller\\{$_name}\\{$_controller}");
  117. $attributes = $reflectionClass->getMethod($action)->getAttributes(NodeAnnotation::class);
  118. foreach ($attributes as $attribute) {
  119. $annotation = $attribute->newInstance();
  120. $bool = $annotation->auth === false;
  121. }
  122. }catch (\Throwable) {
  123. }
  124. return $bool;
  125. }
  126. /**
  127. * 获取当前节点
  128. * @return string
  129. */
  130. public function getCurrentNode()
  131. {
  132. $node = $this->parseNodeStr(request()->controller() . '/' . request()->action());
  133. return $node;
  134. }
  135. /**
  136. * 获取当前管理员所有节点
  137. * @return array
  138. * @throws \think\db\exception\DataNotFoundException
  139. * @throws \think\db\exception\DbException
  140. * @throws \think\db\exception\ModelNotFoundException
  141. */
  142. public function getAdminNode()
  143. {
  144. $nodeList = [];
  145. $adminInfo = Db::name($this->config['system_admin'])
  146. ->where([
  147. 'id' => $this->adminId,
  148. 'status' => 1,
  149. ])->find();
  150. if (!empty($adminInfo) && !empty($adminInfo['auth_ids'])) {
  151. $buildAuthSql = Db::name($this->config['system_auth'])
  152. ->distinct(true)
  153. ->whereIn('id', $adminInfo['auth_ids'])
  154. ->field('id')
  155. ->buildSql(true);
  156. $buildAuthNodeSql = Db::name($this->config['system_auth_node'])
  157. ->distinct(true)
  158. ->where("auth_id IN {$buildAuthSql}")
  159. ->field('node_id')
  160. ->buildSql(true);
  161. $nodeList = Db::name($this->config['system_node'])
  162. ->distinct(true)
  163. ->where("id IN {$buildAuthNodeSql}")
  164. ->column('node');
  165. }
  166. return $nodeList;
  167. }
  168. /**
  169. * 获取所有节点信息
  170. * @time 2021-01-07
  171. * @return array
  172. * @author zhongshaofa <shaofa.zhong@happy-seed.com>
  173. */
  174. public function getNodeList()
  175. {
  176. return Db::name($this->config['system_node'])
  177. ->column('id,node,title,type,is_auth', 'node');
  178. }
  179. /**
  180. * 获取管理员信息
  181. * @time 2021-01-07
  182. * @return array|\think\Model|null
  183. * @throws \think\db\exception\DataNotFoundException
  184. * @throws \think\db\exception\DbException
  185. * @throws \think\db\exception\ModelNotFoundException
  186. * @author zhongshaofa <shaofa.zhong@happy-seed.com>
  187. */
  188. public function getAdminInfo()
  189. {
  190. return Db::name($this->config['system_admin'])
  191. ->where('id', $this->adminId)
  192. ->find();
  193. }
  194. /**
  195. * 驼峰转下划线规则
  196. * @param string $node
  197. * @return string
  198. */
  199. public function parseNodeStr($node)
  200. {
  201. $array = explode('/', $node);
  202. foreach ($array as $key => $val) {
  203. if ($key == 0) {
  204. $val = explode('.', $val);
  205. foreach ($val as &$vo) {
  206. $vo = \think\helper\Str::snake(lcfirst($vo));
  207. }
  208. $val = implode('.', $val);
  209. $array[$key] = $val;
  210. }
  211. }
  212. $node = implode('/', $array);
  213. return $node;
  214. }
  215. }