where('is_active', true) ->whereNotNull('usm') ->where('usm', '!=', '') ->whereNotNull('usm_authentication') ->where('usm_authentication', '!=', ''); $accountId = $this->option('account_id'); if ($accountId !== null && $accountId !== '') { $query->where('id', (int) $accountId); } $accounts = $query->orderBy('id')->get(); if ($accounts->isEmpty()) { $this->line('[]'); return self::SUCCESS; } $rows = []; foreach ($accounts as $account) { $status = $this->checkAccountTokenStatus((string) $account->usm_authentication, (string) $account->usm); $refreshed = false; if ($status === -1 && $this->option('refresh-invalid')) { $refreshed = $this->refreshAccountToken($account); if ($refreshed) { $account->refresh(); $status = $this->checkAccountTokenStatus((string) $account->usm_authentication, (string) $account->usm); } } $rows[] = [ 'id' => $account->id, 'username' => $account->username, 'status' => $status, 'refreshed' => $refreshed, ]; } $this->line(json_encode($rows, JSON_UNESCAPED_UNICODE)); return self::SUCCESS; } private function checkAccountTokenStatus(string $usmAuthentication, string $usm): int { $url = 'https://172.16.254.2/index.php/extend/check_login'; $cookie = sprintf( 'LANG=zh; USM-AUTHENTICATION=%s; USM=%s; LOGON=1; AUTH_METHOD=oauth2', $usmAuthentication, $usm ); try { $response = Http::timeout(10) ->withOptions(['verify' => false]) ->withHeaders([ 'Cookie' => $cookie, 'Accept' => '*/*', ]) ->get($url); } catch (ConnectionException) { return -1; } if (! $response->successful()) { return -1; } return trim((string) $response->body()) === '0' ? 0 : -1; } private function refreshAccountToken(BastionAccount $account): bool { $baseUrl = (string) config('services.bastion_token.base_url'); if ($baseUrl === '') { return false; } $submitEndpoint = (string) config('services.bastion_token.submit_endpoint', '/bastion_token'); $statusEndpoint = (string) config('services.bastion_token.status_endpoint', '/bastion_token/{task_id}'); $timeout = (int) config('services.bastion_token.timeout', 30); $service = (string) config('services.bastion_token.service', 'https://myapp.cdu.edu.cn/index.html'); $verifySsl = (bool) config('services.bastion_token.verify_ssl', false); try { $submitResponse = Http::baseUrl($baseUrl) ->acceptJson() ->timeout($timeout) ->retry(2, 300, throw: false) ->post($submitEndpoint, [ 'username' => $account->username, 'password' => $account->password, 'service' => $service, 'verify_ssl' => $verifySsl, ]); } catch (ConnectionException|RequestException) { return false; } if (! $submitResponse->successful()) { return false; } $taskId = (string) data_get($submitResponse->json(), 'task_id', ''); if ($taskId === '') { return false; } $maxPoll = 20; for ($i = 0; $i < $maxPoll; $i++) { usleep(500000); $statusUrl = str_replace('{task_id}', $taskId, $statusEndpoint); try { $statusResponse = Http::baseUrl($baseUrl) ->acceptJson() ->timeout($timeout) ->retry(2, 300, throw: false) ->get($statusUrl); } catch (ConnectionException|RequestException) { continue; } if (! $statusResponse->successful()) { continue; } $taskResult = $statusResponse->json(); $status = strtolower((string) data_get($taskResult, 'status', 'pending')); if ($status === 'pending') { continue; } if ($status === 'error') { return false; } $usmAuthentication = (string) data_get($taskResult, 'data.bastion.token_cookies.USM-AUTHENTICATION', ''); $usm = (string) data_get($taskResult, 'data.bastion.token_cookies.USM', ''); if ($usmAuthentication === '' || $usm === '') { $usmAuthentication = (string) data_get($taskResult, 'data.USM-AUTHENTICATION', $usmAuthentication); $usm = (string) data_get($taskResult, 'data.USM', $usm); } if ($usmAuthentication === '' || $usm === '') { return false; } $account->update([ 'usm_authentication' => $usmAuthentication, 'usm' => $usm, 'last_token_refreshed_at' => now(), ]); return true; } return false; } }