AdminAuth.php 8.1 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211
  1. <?php
  2. namespace App\Http\Middleware;
  3. use Closure;
  4. use Illuminate\Http\Request;
  5. use Illuminate\Support\Facades\DB;
  6. class AdminAuth
  7. {
  8. // 无需验证的路径
  9. protected $except = [
  10. 'admin/login/index',
  11. 'admin/login/send_code',
  12. 'admin/login/out',
  13. 'admin/files_manager/add', // 文件上传
  14. 'admin/contact_way/part_user', // 接待人员
  15. 'admin/product/get_spec_html', // 获取类型下的规格
  16. 'admin/product/get_sku_html', // 获取sku
  17. 'admin/image_manager/index', // 获取sku
  18. 'admin/image_manager/upload', // 获取sku
  19. 'admin/image_manager/folder', // 获取sku
  20. 'admin/image_manager/delete', // 获取sku
  21. 'admin/ueditor/upload', // 获取sku
  22. 'admin/orders/get_school'
  23. ];
  24. //默认配置
  25. protected $_config = [
  26. 'auth_on' => true, // 认证开关
  27. 'auth_type' => 1, // 认证方式,1为实时认证;2为登录认证。
  28. 'auth_group' => 'auth_group', // 用户组数据表名
  29. 'auth_group_access' => 'auth_group_access', // 用户-用户组关系表
  30. 'auth_rule' => 'auth_rule' // 权限规则表
  31. ];
  32. /**
  33. * $prefix表前缀
  34. */
  35. public function __construct()
  36. {
  37. // 判断配置
  38. if ( config('AUTH_CONFIG') ) {
  39. //可设置配置项 AUTH_CONFIG, 此配置项为数组。
  40. $this->_config = array_merge($this->_config, config('AUTH_CONFIG'));
  41. }
  42. }
  43. /**
  44. * Handle an incoming request.
  45. *
  46. * @param \Illuminate\Http\Request $request
  47. * @param \Closure $next
  48. * @return mixed
  49. */
  50. public function handle(Request $request, Closure $next)
  51. {
  52. // 当前路径
  53. $path = ltrim($request->getPathInfo(), '/');
  54. // 判断是否需要验证登录
  55. if (!in_array($path, $this->except)) {
  56. // 如果没有登录,重定向到登录页
  57. if ( !admin('uid')) $this->unLogin($request);
  58. // 如果不是超级管理员
  59. if ( !in_array(admin('uid'), explode(',', config('administrator'))) ) {
  60. // 进行验证
  61. if ( !$this->check($path, admin('uid')) ) $this->noAuth('没有权限!');
  62. }
  63. }
  64. // 追加入
  65. $request['authRules'] = $this->getAuthList(admin('uid'),1);
  66. // 返回下一个闭包
  67. return $next($request);
  68. }
  69. /**
  70. * Handle an unauthenticated user.
  71. *
  72. * @param \Illuminate\Http\Request $request
  73. * @return void
  74. *
  75. * @throws AdminAuthException
  76. */
  77. protected function unLogin($request)
  78. {
  79. throw new \App\Exceptions\Admin\AuthException('请先登录',$this->redirectTo($request),0);
  80. }
  81. /**
  82. * Handle an unauthenticated user.
  83. *
  84. * @param \Illuminate\Http\Request $request
  85. * @return void
  86. *
  87. * @throws AdminAuthException
  88. */
  89. protected function noAuth($msg,$url='',$wait=3)
  90. {
  91. throw new \App\Exceptions\Admin\AuthException($msg,$url,$wait);
  92. }
  93. /**
  94. * Get the path the user should be redirected to when they are not authenticated.
  95. *
  96. * @param \Illuminate\Http\Request $request
  97. * @return string|null
  98. */
  99. protected function redirectTo($request)
  100. {
  101. if (!$request->expectsJson()) return route('login');
  102. }
  103. /**
  104. * 检查权限
  105. * @param name string|array 需要验证的规则列表
  106. * @param uid int 认证用户的id
  107. * @return boolean 通过验证返回true;失败返回false
  108. */
  109. public function check($path, $uid, $type = 1)
  110. {
  111. // 未开启验证,直接通过
  112. if ( !$this->_config['auth_on'] ) return true;
  113. // 获取用户需要验证的所有有效规则列表
  114. $authList = $this->getAuthList($uid, $type);
  115. // 切割path
  116. $path = explode('/', $path);
  117. // 没有控制器
  118. if( count($path) < 2 ) $path[] = 'index';
  119. // 没有方法
  120. if( count($path) < 3 ) $path[] = 'index';
  121. // 切割path
  122. $path = implode('/', $path);
  123. // 判断是否通过验证
  124. return in_array($path, $authList);
  125. }
  126. /**
  127. * 根据用户id获取用户组,返回值为数组
  128. * @param int $uid 用户id
  129. * @return array 用户所属的用户组
  130. */
  131. public function getGroups($uid)
  132. {
  133. // 用户组
  134. static $groups = [];
  135. // 存在小组,返回
  136. if ( isset($groups[$uid]) ) return $groups[$uid];
  137. // 从数据库查询
  138. $userrGroups = DB::table($this->_config['auth_group_access'])
  139. ->where([[$this->_config['auth_group_access'].'.user_uid','=',$uid],[$this->_config['auth_group'].'.status','=',1]])
  140. ->join( $this->_config['auth_group'], $this->_config['auth_group_access'].'.group_id','=',$this->_config['auth_group'].'.id')
  141. ->select(['user_uid as uid','group_id','title','rules'])->get()->toArray();
  142. // 获取对应用户的权限组
  143. $groups[$uid] = $userrGroups ?: [];
  144. // 返回用户的权限组
  145. return $groups[$uid];
  146. }
  147. /**
  148. * 获得权限列表
  149. * @param integer $uid 用户id
  150. * @param integer $type
  151. */
  152. protected function getAuthList($uid, $type)
  153. {
  154. // 保存用户验证通过的权限列表
  155. static $_authList = [];
  156. // 验证类型
  157. $key = $uid .'_t_'.implode(',', (array) $type);
  158. // 已经存在权限列表,直接返回
  159. if (isset($_authList[$key])) return $_authList[$key];
  160. // 验证类型,如果不是实时验证
  161. if ( $this->_config['auth_type'] == 2 ) {
  162. // 从session读取验证列表
  163. $session = session('_AUTH_LIST_'.$key);
  164. // 存在则返回
  165. if( !empty($session) ) return $session;
  166. }
  167. // 读取用户所属用户组
  168. $groups = $this->getGroups($uid);
  169. // 保存用户所属用户组设置的所有权限规则id
  170. $ids = [];
  171. // 获取字段值
  172. $ids = array_column($groups,'rules');
  173. // 合并字符值
  174. $ids = array_unique(array_filter(explode(',',implode(',',$ids))));
  175. // 为空
  176. if( empty($ids) ) return [];
  177. // 读取用户组所有权限规则
  178. $rules = Db::table($this->_config['auth_rule'])->whereIn('menu_id',$ids)->pluck('name')->toArray();
  179. // 循环转大写
  180. foreach ( $rules as $rule ) {
  181. // 转小写,截除左边斜杠
  182. $rules[] = ltrim(strtolower($rule),'/');
  183. }
  184. // 去重
  185. $rules = array_unique($rules);
  186. // 如果是登录验证
  187. if ($this->_config['auth_type'] == 2 ) {
  188. // 用户验证列表
  189. $rules[$key] = $rules;
  190. //规则列表结果保存到session
  191. session('_AUTH_LIST_'.$key,$rules);
  192. }
  193. // 返回结果
  194. return $rules;
  195. }
  196. }