initializeApi($request); if ($response !== null) { return $response; } $signature = $request->get('signature', ''); $secret = $request->get('secret', ''); $agentId = $request->get('agent_id', ''); $time = $request->get('time', ''); if ($signature === '' || $secret === '' || $agentId === '' || $time === '') { return $this->error(__('Parameter signature/secret/agent_id/time can not be empty')); } $timestamp = intval($time); if ($timestamp <= 0) { return $this->error(__('Invalid timestamp')); } $now = time(); if ($timestamp < $now - $this->timeTolerance || $timestamp > $now + $this->timeTolerance) { return $this->error(__('Timestamp expired')); } $admin = Admin::where('agent_id', $agentId)->find(); if (!$admin) { return $this->error(__('Agent not found')); } $apiSecret = strval($admin->agent_api_secret ?? ''); if ($apiSecret === '') { return $this->error(__('Agent not found')); } if ($apiSecret !== $secret) { return $this->error(__('Invalid agent or secret')); } $expectedSignature = strtoupper(md5($agentId . $secret . $time)); if (!hash_equals($expectedSignature, $signature)) { return $this->error(__('Invalid signature')); } $expire = intval(config('buildadmin.agent_auth.token_expire', 86400)); $payload = [ 'agent_id' => $agentId, 'admin_id' => $admin->id, ]; $authtoken = AgentJwt::encode($payload, $expire); return $this->success('', [ 'authtoken' => $authtoken, ]); } /** * H5 临时登录(GET/POST) * 参数:username * 写入或复用 mall_user_asset;签发 muser 类型 token(user_id 为资产表主键) */ public function temLogin(Request $request): Response { $response = $this->initializeApi($request); if ($response !== null) { return $response; } $enabled = config('buildadmin.agent_auth.temp_login_enable', false); if (!$enabled) { return $this->error(__('Temp login is disabled')); } $username = trim(strval($request->get('username', $request->post('username', '')))); // 兼容:querystring 中未编码的 '+' 会被解析为空格(application/x-www-form-urlencoded 规则) // 例如:/api/v1/temLogin?username=+607... 期望保留 '+',则从原始 querystring 提取并还原 if ($username !== '' && str_contains($username, ' ')) { $qs = $request->queryString(); if (is_string($qs) && $qs !== '') { foreach (explode('&', $qs) as $pair) { if ($pair === '' || !str_contains($pair, '=')) { continue; } [$k, $v] = explode('=', $pair, 2); if (rawurldecode($k) === 'username') { // 先把 %xx 解码;注意这里不把 '+' 当空格处理,从而保留 '+' $username = trim(rawurldecode($v)); break; } } } } if ($username === '') { return $this->error(__('Parameter username can not be empty')); } try { $asset = MallUserAsset::ensureForUsername($username); } catch (Throwable $e) { return $this->error($e->getMessage()); } $token = Random::uuid(); $refreshToken = Random::uuid(); $expire = config('buildadmin.agent_auth.temp_login_expire', $this->tempTokenExpire); $assetId = intval($asset->getKey()); Token::set($token, UserAuth::TOKEN_TYPE_MALL_USER, $assetId, $expire); Token::set($refreshToken, UserAuth::TOKEN_TYPE_MALL_USER . '-refresh', $assetId, 2592000); return $this->success('', [ 'userInfo' => [ 'id' => $assetId, 'username' => strval($asset->username ?? ''), 'nickname' => strval($asset->username ?? ''), 'playx_user_id' => strval($asset->playx_user_id ?? ''), 'token' => $token, 'refresh_token' => $refreshToken, 'expires_in' => $expire, ], ]); } }