setKeepTime((int)Config::get('buildadmin.admin_token_keep_time')); } /** * 魔术方法-管理员信息字段 * @param $name * @return mixed 字段信息 */ public function __get($name): mixed { return $this->model[$name]; } /** * 初始化 * @access public * @param array $options 传递到 /ba/Auth 的配置信息 * @return Auth */ public static function instance(array $options = []): Auth { $request = request(); if (!isset($request->adminAuth)) { $request->adminAuth = new static($options); } return $request->adminAuth; } /** * 根据Token初始化管理员登录态 * @param string $token * @return bool * @throws Throwable */ public function init(string $token): bool { // $tokenData = Token::get($token); $jwtUtil = (new JwtUtils()); $tokenData = $jwtUtil->getClaimByToken($token); if ($tokenData) { /** * 过期检查,过期则抛出 @see TokenExpirationException */ // Token::tokenExpirationCheck($tokenData); // $userId = intval($tokenData['user_id']); $userId = $tokenData->sub; if (!isset($tokenData->type) || ($tokenData->type == self::TOKEN_TYPE && $userId > 0)) { $this->user_id_slave_connect_db = Db::connect(DatabaseRoute::getConnection('sys_user', ['user_id' => $userId])); $this->model = $this->user_id_slave_connect_db->name('sys_user')->where('user_id', $userId)->find(); if (!$this->model) { $this->setError('Account not exist'); return false; } if ($this->model['status'] != '1') { $this->setError('Account disabled'); return false; } $this->token = $token; $this->loginSuccessful(); return true; } } $this->setError('Token login failed'); $this->reset(); return false; } /** * 管理员登录 * @param string $username 用户名 * @param string $password 密码 * @param bool $keep 是否保持登录 * @return bool * @throws Throwable */ public function login(string $username, string $password, bool $keep = false): bool { $this->model = SysUser::GetByusername($username); if (!$this->model) { $this->setError('未注册, 请先注册'); return false; } if ($this->model['status'] != 1) { $this->setError('账号已被禁用,请联系客服处理!'); return false; } if(empty($this->model['password'])) { $this->setError('当前账号未绑定密码,请前往忘记密码中进行重置!'); return false; } $pwd = shiro_simple_hash_hex_salt('sha256', $password, $this->model['salt']); // 验证密码 if($pwd == $this->model['password']) { $this->loginSuccessful(); return true; }else { $this->setError('账号或密码不正确!'); return false; } } /** * 设置刷新Token * @param int $keepTime */ public function setRefreshToken(int $keepTime = 0): void { $this->refreshToken = Random::uuid(); Token::set($this->refreshToken, self::TOKEN_TYPE . '-refresh', $this->model->id, $keepTime); } /** * 管理员登录成功 * @return bool */ public function loginSuccessful(): bool { if (!$this->model) return false; try { $this->loginEd = true; if (!$this->token) { // $this->token = Random::uuid(); $this->token = (new JwtUtils())->generateToken($this->model['user_id'], 'admin'); // Token::set($this->token, self::TOKEN_TYPE, $this->model['user_id'], $this->keepTime); } } catch (Throwable $e) { $this->setError($e->getMessage()); return false; } return true; } /** * 管理员登录失败 * @return bool */ public function loginFailed(): bool { if (!$this->model) return false; $this->model->startTrans(); try { $this->model->login_failure++; $this->model->last_login_time = time(); $this->model->last_login_ip = request()->ip(); $this->model->save(); $this->model->commit(); } catch (Throwable $e) { $this->model->rollback(); $this->setError($e->getMessage()); return false; } return $this->reset(); } /** * 退出登录 * @return bool */ public function logout(): bool { if (!$this->loginEd) { $this->setError('You are not logged in'); return false; } return $this->reset(); } /** * 是否登录 * @return bool */ public function isLogin(): bool { return $this->loginEd; } /** * 获取管理员模型 * @return Admin */ public function getAdmin() { return $this->model; } /** * 获取管理员Token * @return string */ public function getToken(): string { return $this->token; } /** * 获取管理员刷新Token * @return string */ public function getRefreshToken(): string { return $this->refreshToken; } /** * 获取管理员信息 - 只输出允许输出的字段 * @return array */ public function getInfo(): array { if (!$this->model) return []; $info = $this->model->toArray(); $info = array_intersect_key($info, array_flip($this->getAllowFields())); $info['token'] = $this->getToken(); $info['refresh_token'] = $this->getRefreshToken(); return $info; } /** * 获取允许输出字段 * @return array */ public function getAllowFields(): array { return $this->allowFields; } /** * 设置允许输出字段 * @param $fields * @return void */ public function setAllowFields($fields): void { $this->allowFields = $fields; } /** * 设置Token有效期 * @param int $keepTime * @return void */ public function setKeepTime(int $keepTime = 0): void { $this->keepTime = $keepTime; } public function checkmenus($url, $uid): bool { return parent::checkmenus($url, $uid ?: $this->user_id); } public function getUserMenus($uid):array { return parent::getUserMenus($uid); } public function check(string $name, int $uid = 0, string $relation = 'or', string $mode = 'url'): bool { return parent::check($name, $uid ?: $this->id, $relation, $mode); } public function getGroups(int $uid = 0): array { return parent::getGroups($uid ?: $this->id); } public function getRuleList(int $uid = 0): array { return parent::getRuleList($uid ?: $this->id); } public function getRuleIds(int $uid = 0): array { return parent::getRuleIds($uid ?: $this->id); } public function getMenus(int $uid = 0): array { return parent::getMenus($uid ?: $this->id); } /** * 是否是超级管理员 * @throws Throwable */ public function isSuperAdmin(): bool { return in_array('*', $this->getRuleIds()); } /** * 获取管理员所在分组的所有子级分组 * @return array * @throws Throwable */ public function getAdminChildGroups(): array { $groupIds = Db::name('admin_group_access') ->where('uid', $this->id) ->select(); $children = []; foreach ($groupIds as $group) { $this->getGroupChildGroups($group['group_id'], $children); } return array_unique($children); } /** * 获取一个分组下的子分组 * @param int $groupId 分组ID * @param array $children 存放子分组的变量 * @return void * @throws Throwable */ public function getGroupChildGroups(int $groupId, array &$children): void { $childrenTemp = AdminGroup::where('pid', $groupId) ->where('status', 1) ->select(); foreach ($childrenTemp as $item) { $children[] = $item['id']; $this->getGroupChildGroups($item['id'], $children); } } /** * 获取分组内的管理员 * @param array $groups * @return array 管理员数组 */ public function getGroupAdmins(array $groups): array { return Db::name('admin_group_access') ->where('group_id', 'in', $groups) ->column('uid'); } /** * 获取拥有 `所有权限` 的分组 * @param string $dataLimit 数据权限 * @param array $groupQueryWhere 分组查询条件(默认查询启用的分组:[['status','=',1]]) * @return array 分组数组 * @throws Throwable */ public function getAllAuthGroups(string $dataLimit, array $groupQueryWhere = [['status', '=', 1]]): array { // 当前管理员拥有的权限 $rules = $this->getRuleIds(); $allAuthGroups = []; $groups = AdminGroup::where($groupQueryWhere)->select(); foreach ($groups as $group) { if ($group['rules'] == '*') { continue; } $groupRules = explode(',', $group['rules']); // 及时break, array_diff 等没有 in_array 快 $all = true; foreach ($groupRules as $groupRule) { if (!in_array($groupRule, $rules)) { $all = false; break; } } if ($all) { if ($dataLimit == 'allAuth' || ($dataLimit == 'allAuthAndOthers' && array_diff($rules, $groupRules))) { $allAuthGroups[] = $group['id']; } } } return $allAuthGroups; } /** * 设置错误消息 * @param $error * @return Auth */ public function setError($error): Auth { $this->error = $error; return $this; } /** * 获取错误消息 * @return string */ public function getError(): string { return $this->error ? __($this->error) : ''; } /** * 属性重置(注销、登录失败、重新初始化等将单例数据销毁) */ protected function reset(bool $deleteToken = true): bool { if ($deleteToken && $this->token) { // Token::delete($this->token); } $this->token = ''; $this->loginEd = false; $this->model = null; $this->refreshToken = ''; $this->setError(''); $this->setKeepTime((int)Config::get('buildadmin.admin_token_keep_time')); return true; } }