data([ 'enabled' => (new IamOidcService())->enabled(), ]); } public function iamStart() { try { return redirect((new IamOidcService())->begin()); } catch (IamHubException $error) { return json(['code' => 0, 'show' => 1, 'msg' => $error->getMessage(), 'data' => []], $error->httpStatus()); } } public function iamCallback() { $successUrl = (string) config('iam_hub.login_success_url', '/admin/login'); try { $code = trim((string) $this->request->get('code', '')); $state = trim((string) $this->request->get('state', '')); if ($code === '' || $state === '') { throw new IamHubException('统一身份登录回调参数缺失'); } $claims = (new IamOidcService())->callback($code, $state); $login = (new IamAdminIdentityService())->login($claims, 1); $exchange = new IamExchangeService((int) config('iam_hub.exchange_ttl_seconds', 60)); $exchangeCode = $exchange->store($login); return redirect($successUrl . '#iam_code=' . rawurlencode($exchangeCode)); } catch (\Throwable $error) { Log::error('IAM Hub admin login callback failed: ' . get_class($error)); return redirect($successUrl . '#iam_error=1'); } } public function iamExchange() { $code = trim((string) $this->request->post('code', '')); $exchange = new IamExchangeService((int) config('iam_hub.exchange_ttl_seconds', 60)); $login = $exchange->consume($code); if ($login === null) { return $this->fail('统一身份登录凭证无效或已过期'); } return $this->data($login); } /** * @notes 账号登录 * @date 2021/6/30 17:01 * @return \think\response\Json * @throws \think\db\exception\DataNotFoundException * @throws \think\db\exception\DbException * @throws \think\db\exception\ModelNotFoundException * @author 令狐冲 */ public function account() { $params = (new LoginValidate())->post()->goCheck(); return $this->data((new LoginLogic())->login($params)); } /** * @notes 获取企业微信登录配置(前端构造OAuth URL/扫码用) */ public function workWechatConfig() { $corpId = env('work_wechat.corp_id', ''); $agentId = env('work_wechat.agent_id', ''); if (empty($corpId) || empty($agentId)) { return $this->data([ 'enabled' => false, 'require_bind_nonroot' => false, 'force_bind_login' => LoginLogic::isForceBindWorkWechatFromEnv(), ]); } $oauthOk = LoginLogic::isWorkWechatOAuthConfigured(); $forceBind = LoginLogic::isForceBindWorkWechatFromEnv(); return $this->data([ 'enabled' => true, 'corp_id' => $corpId, 'agent_id' => $agentId, /** 与 .env FORCE_BIND_LOGIN 一致:为 true 且 OAuth 配全时非 root 须先绑定 */ 'require_bind_nonroot' => $forceBind && $oauthOk, 'force_bind_login' => $forceBind, ]); } /** * @notes 企业微信授权登录(用 code 换 token) */ public function workWechatLogin() { $code = $this->request->post('code', ''); if (empty($code)) { return $this->fail('缺少授权code'); } $terminal = $this->request->post('terminal', 1); $result = (new LoginLogic())->workWechatLogin([ 'code' => $code, 'terminal' => $terminal, ]); if ($result === false) { return $this->fail(LoginLogic::getError()); } return $this->data($result); } /** * @notes 临时调试:检查 admin 表是否有 work_wechat_userid 列(确认后请删除此方法) */ public function checkDbColumn() { $dbName = env('database.database', ''); $prefix = env('database.prefix', ''); $tableName = $prefix . 'admin'; $columns = \think\facade\Db::query("SHOW COLUMNS FROM `{$tableName}` LIKE 'work_wechat_userid'"); return $this->data([ 'database' => $dbName, 'table' => $tableName, 'column_exists' => !empty($columns), 'columns_result' => $columns, ]); } /** * @notes 首次登录修改密码 * @return \think\response\Json */ public function changeFirstPassword() { $password = $this->request->post('password', ''); $passwordConfirm = $this->request->post('password_confirm', ''); if (empty($password)) { return $this->fail('请输入新密码'); } if (strlen($password) < 6) { return $this->fail('密码长度不能少于6位'); } if ($password !== $passwordConfirm) { return $this->fail('两次输入的密码不一致'); } $token = $this->request->header('token'); if (empty($token)) { return $this->fail('请先登录'); } $result = (new LoginLogic())->changeFirstPassword($token, $password); if ($result === false) { return $this->fail(LoginLogic::getError()); } return $this->success('密码修改成功'); } /** * @notes 退出登录 * @return \think\response\Json * @throws \think\db\exception\DataNotFoundException * @throws \think\db\exception\DbException * @throws \think\db\exception\ModelNotFoundException * @author 令狐冲 * @date 2021/7/8 00:36 */ public function logout() { //退出登录情况特殊,只有成功的情况,也不需要token验证 (new LoginLogic())->logout($this->adminInfo); return $this->success(); } }