api_client.rs 49 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586878889909192939495969798991001011021031041051061071081091101111121131141151161171181191201211221231241251261271281291301311321331341351361371381391401411421431441451461471481491501511521531541551561571581591601611621631641651661671681691701711721731741751761771781791801811821831841851861871881891901911921931941951961971981992002012022032042052062072082092102112122132142152162172182192202212222232242252262272282292302312322332342352362372382392402412422432442452462472482492502512522532542552562572582592602612622632642652662672682692702712722732742752762772782792802812822832842852862872882892902912922932942952962972982993003013023033043053063073083093103113123133143153163173183193203213223233243253263273283293303313323333343353363373383393403413423433443453463473483493503513523533543553563573583593603613623633643653663673683693703713723733743753763773783793803813823833843853863873883893903913923933943953963973983994004014024034044054064074084094104114124134144154164174184194204214224234244254264274284294304314324334344354364374384394404414424434444454464474484494504514524534544554564574584594604614624634644654664674684694704714724734744754764774784794804814824834844854864874884894904914924934944954964974984995005015025035045055065075085095105115125135145155165175185195205215225235245255265275285295305315325335345355365375385395405415425435445455465475485495505515525535545555565575585595605615625635645655665675685695705715725735745755765775785795805815825835845855865875885895905915925935945955965975985996006016026036046056066076086096106116126136146156166176186196206216226236246256266276286296306316326336346356366376386396406416426436446456466476486496506516526536546556566576586596606616626636646656666676686696706716726736746756766776786796806816826836846856866876886896906916926936946956966976986997007017027037047057067077087097107117127137147157167177187197207217227237247257267277287297307317327337347357367377387397407417427437447457467477487497507517527537547557567577587597607617627637647657667677687697707717727737747757767777787797807817827837847857867877887897907917927937947957967977987998008018028038048058068078088098108118128138148158168178188198208218228238248258268278288298308318328338348358368378388398408418428438448458468478488498508518528538548558568578588598608618628638648658668678688698708718728738748758768778788798808818828838848858868878888898908918928938948958968978988999009019029039049059069079089099109119129139149159169179189199209219229239249259269279289299309319329339349359369379389399409419429439449459469479489499509519529539549559569579589599609619629639649659669679689699709719729739749759769779789799809819829839849859869879889899909919929939949959969979989991000100110021003100410051006100710081009101010111012101310141015101610171018101910201021102210231024102510261027102810291030103110321033103410351036103710381039104010411042104310441045104610471048104910501051105210531054105510561057105810591060106110621063106410651066106710681069107010711072107310741075107610771078107910801081108210831084108510861087108810891090109110921093109410951096109710981099110011011102110311041105110611071108110911101111111211131114111511161117111811191120112111221123112411251126112711281129113011311132113311341135113611371138113911401141114211431144114511461147114811491150115111521153115411551156115711581159116011611162
  1. use reqwest::Client;
  2. use serde::{Deserialize, Serialize};
  3. use std::collections::HashMap;
  4. use std::time::Duration;
  5. use base64::{Engine as _, engine::general_purpose};
  6. use rsa::{RsaPublicKey, pkcs1::DecodeRsaPublicKey, Oaep, sha2::Sha256};
  7. use rsa::pkcs8::DecodePublicKey;
  8. use openssl::symm::{encrypt, Cipher as OpenSSLCipher};
  9. use rand::rngs::OsRng;
  10. use rand::RngCore;
  11. use openssl::pkey::PKey;
  12. use openssl::sign::Verifier;
  13. use openssl::hash::MessageDigest;
  14. use openssl::rsa::Padding;
  15. use crate::error::{ClientError, network_error, serialization_error, rsa_error, aes_error, config_error};
  16. use crate::machine::generate_machine_code;
  17. #[derive(Debug, Serialize, Deserialize, Clone)]
  18. pub struct ApiConfig {
  19. pub base_url: String,
  20. pub timeout: u64,
  21. pub software_code: String,
  22. }
  23. impl Default for ApiConfig {
  24. fn default() -> Self {
  25. ApiConfig {
  26. base_url: "http://125.122.32.114:9000".to_string(),
  27. timeout: 30,
  28. software_code: "buff-xp-steam-sh".to_string(),
  29. }
  30. }
  31. }
  32. #[derive(Debug, Serialize, Deserialize)]
  33. pub struct ApiResponse<T> {
  34. pub code: i32,
  35. pub msg: String,
  36. pub data: Option<T>,
  37. }
  38. #[derive(Debug, Serialize, Deserialize)]
  39. pub struct UserInfo {
  40. #[serde(rename = "user_id")]
  41. pub id: Option<i32>,
  42. pub username: String,
  43. #[serde(default)]
  44. pub email: Option<String>,
  45. #[serde(default)]
  46. pub expire_time: Option<String>,
  47. #[serde(default)]
  48. pub is_active: Option<bool>,
  49. #[serde(default)]
  50. pub session_id: Option<String>,
  51. }
  52. #[derive(Debug, Serialize, Deserialize)]
  53. pub struct SteamAccount {
  54. pub id: i32,
  55. pub steam_username: String,
  56. #[serde(default)]
  57. pub steam_id: Option<String>,
  58. pub is_active: bool,
  59. pub created_at: String,
  60. #[serde(default)]
  61. pub updated_at: Option<String>,
  62. }
  63. #[derive(Debug, Serialize, Deserialize)]
  64. pub struct SteamAccountLimitData {
  65. pub max_steam_accounts: i32,
  66. pub current_bound_count: i32,
  67. }
  68. #[derive(Debug, Serialize, Deserialize, Clone)]
  69. pub struct Announcement {
  70. pub id: i32,
  71. pub title: String,
  72. pub content: String,
  73. #[serde(default = "default_is_active")]
  74. pub is_active: bool,
  75. #[serde(rename = "publish_time")]
  76. pub created_at: String,
  77. }
  78. fn default_is_active() -> bool {
  79. true
  80. }
  81. #[derive(Debug, Serialize, Deserialize, Clone)]
  82. pub struct PublicKeyData {
  83. pub public_key: String,
  84. #[serde(default)]
  85. pub key_version: Option<i32>,
  86. #[serde(default)]
  87. pub signing_public_key: Option<String>,
  88. }
  89. pub struct BackendApiClient {
  90. client: Client,
  91. config: ApiConfig,
  92. public_key: Option<RsaPublicKey>,
  93. public_keys: std::collections::HashMap<i32, RsaPublicKey>, // 多版本公钥缓存:版本号 -> 公钥
  94. key_order: Vec<i32>, // LRU order: oldest at index 0
  95. current_key_version: Option<i32>, // 当前使用的密钥版本
  96. session_id: Option<String>,
  97. current_user_id: Option<i32>,
  98. current_username: Option<String>,
  99. }
  100. impl BackendApiClient {
  101. pub fn new(config: ApiConfig) -> Result<Self, ClientError> {
  102. // 验证配置
  103. if config.base_url.trim().is_empty() {
  104. return Err(config_error("API基础URL不能为空"));
  105. }
  106. if config.timeout == 0 {
  107. return Err(config_error("超时时间不能为0"));
  108. }
  109. if config.software_code.trim().is_empty() {
  110. return Err(config_error("软件特征码不能为空"));
  111. }
  112. // 复用全局共享的 reqwest Client(带连接池)
  113. let client = get_http_client();
  114. Ok(BackendApiClient {
  115. client,
  116. config,
  117. public_key: None,
  118. public_keys: std::collections::HashMap::new(),
  119. key_order: Vec::new(),
  120. current_key_version: None,
  121. session_id: None,
  122. current_user_id: None,
  123. current_username: None,
  124. })
  125. }
  126. // 设置会话ID
  127. pub fn set_session_id(&mut self, session_id: String) {
  128. self.session_id = Some(session_id);
  129. }
  130. #[allow(dead_code)]
  131. pub fn set_current_user(&mut self, user_id: Option<i32>, username: Option<String>) {
  132. self.current_user_id = user_id;
  133. self.current_username = username;
  134. }
  135. // 获取当前会话ID
  136. #[allow(dead_code)]
  137. pub fn get_session_id(&self) -> Option<&String> {
  138. self.session_id.as_ref()
  139. }
  140. // 清除会话
  141. #[allow(dead_code)]
  142. pub fn clear_session(&mut self) {
  143. self.session_id = None;
  144. self.current_user_id = None;
  145. self.current_username = None;
  146. }
  147. // 获取指定版本的RSA公钥
  148. #[allow(dead_code)]
  149. async fn fetch_public_key_by_version(&mut self, key_version: i32) -> Result<RsaPublicKey, ClientError> {
  150. // 如果已缓存该版本的公钥,直接返回克隆
  151. if let Some(pk) = self.public_keys.get(&key_version) {
  152. return Ok(pk.clone());
  153. }
  154. let url = format!("{}/api/v1/keys/version", self.config.base_url);
  155. let response = self.client.get(&url).send().await?;
  156. let response_text = response.text().await?;
  157. // 调试:打印后端原始响应(前 1024 字符)以定位解析错误
  158. {
  159. let prefix_len = std::cmp::min(1024, response_text.len());
  160. eprintln!("client response debug (prefix {}): {}", prefix_len, &response_text[..prefix_len]);
  161. }
  162. #[derive(Deserialize)]
  163. struct PublicKeyResponse {
  164. code: i32,
  165. data: Option<PublicKeyData>,
  166. }
  167. #[derive(Deserialize)]
  168. struct PublicKeyData {
  169. current_version: i32,
  170. available_versions: Vec<i32>,
  171. public_key: String,
  172. #[serde(default)]
  173. signing_public_key: Option<String>,
  174. }
  175. let api_response: PublicKeyResponse = serde_json::from_str(&response_text)?;
  176. if api_response.code == 200 {
  177. if let Some(data) = api_response.data {
  178. // 后端返回的是 "-----BEGIN PUBLIC KEY-----" (PKCS#8 SubjectPublicKeyInfo)
  179. // 先尝试按 PKCS#8 解析,如果失败再回退到 PKCS#1 ("RSA PUBLIC KEY")
  180. let public_key = match RsaPublicKey::from_public_key_pem(&data.public_key) {
  181. Ok(pk) => pk,
  182. Err(_) => {
  183. // 回退到 PKCS#1 解析
  184. RsaPublicKey::from_pkcs1_pem(&data.public_key)
  185. .map_err(|e| ClientError::RsaError {
  186. message: format!("RSA公钥解析失败: {}", e),
  187. })?
  188. }
  189. };
  190. // 缓存该版本的公钥 (LRU cache, keep max 3)
  191. self.public_keys.insert(data.current_version, public_key.clone());
  192. // update key_order: move to back
  193. self.key_order.retain(|&v| v != data.current_version);
  194. self.key_order.push(data.current_version);
  195. // evict oldest if over limit
  196. if self.key_order.len() > 3 {
  197. if let Some(old_v) = self.key_order.first().cloned() {
  198. self.public_keys.remove(&old_v);
  199. self.key_order.remove(0);
  200. }
  201. }
  202. self.current_key_version = Some(data.current_version);
  203. Ok(public_key)
  204. } else {
  205. Err(ClientError::ApiBusinessError {
  206. code: 500,
  207. message: "服务器返回数据为空".to_string(),
  208. })
  209. }
  210. } else {
  211. Err(ClientError::ApiBusinessError {
  212. code: api_response.code,
  213. message: "获取公钥失败".to_string(),
  214. })
  215. }
  216. }
  217. // 获取RSA公钥(兼容性方法,使用当前激活版本)
  218. async fn fetch_public_key(&mut self) -> Result<RsaPublicKey, ClientError> {
  219. // 如果已缓存公钥,直接返回克隆
  220. if let Some(pk) = &self.public_key {
  221. log::info!("[fetch_public_key] 使用缓存公钥 current_key_version={:?}", self.current_key_version);
  222. return Ok(pk.clone());
  223. }
  224. log::info!("[fetch_public_key] 无缓存,发起 POST /keys/public 握手");
  225. // 服务器期望通过 POST 提交临时 AES 密钥以返回加密的公钥数据
  226. let url = format!("{}/api/v1/keys/public", self.config.base_url);
  227. // 1) 生成随机 AES 密钥(32 bytes)并 base64 编码
  228. let mut rng = OsRng;
  229. let mut aes_key: [u8; 32] = [0u8; 32];
  230. rng.fill_bytes(&mut aes_key);
  231. let aes_key_b64 = general_purpose::STANDARD.encode(&aes_key);
  232. eprintln!("[fetch_public_key] aes_key len={} aes_key_b64 len={}", aes_key.len(), aes_key_b64.len());
  233. // 2) 生成 timestamp 和 nonce
  234. let timestamp = std::time::SystemTime::now()
  235. .duration_since(std::time::UNIX_EPOCH)
  236. .map_err(|e| ClientError::UnknownError { message: format!("获取时间戳失败: {}", e) })?
  237. .as_secs() as i64;
  238. let mut nonce_bytes: [u8; 16] = [0u8; 16];
  239. rng.fill_bytes(&mut nonce_bytes);
  240. let nonce = nonce_bytes.iter().map(|b| format!("{:02x}", b)).collect::<String>();
  241. // 3) 生成加密的机器特征信息(encrypted_params)
  242. // generate_machine_code 当前返回原始特征字符串,例如 "DISK=...;MAC=..."
  243. let raw_machine_info = generate_machine_code()
  244. .unwrap_or_else(|_| "UNKNOWN_MACHINE".to_string());
  245. let encrypted_params_bytes = encrypt(
  246. OpenSSLCipher::aes_256_cbc(),
  247. &aes_key,
  248. // 这里复用 aes_key 的后16字节作为 IV,与响应解密时的约定保持一致
  249. Some(&aes_key[16..32]),
  250. raw_machine_info.as_bytes(),
  251. ).map_err(|e| aes_error(format!("加密机器特征信息失败: {}", e)))?;
  252. let encrypted_params_b64 = general_purpose::STANDARD.encode(&encrypted_params_bytes);
  253. // Retry handshake up to 2 attempts if signature verification fails
  254. let mut last_err: Option<ClientError> = None;
  255. for attempt in 0..2 {
  256. // 4) 构造请求体并发送 POST(明文)
  257. let request_body = serde_json::json!({
  258. "encrypted_params": encrypted_params_b64,
  259. "aes_key": aes_key_b64,
  260. "timestamp": timestamp,
  261. "nonce": nonce
  262. });
  263. let response = self.client.post(&url)
  264. .header("Content-Type", "application/json")
  265. .json(&request_body)
  266. .send()
  267. .await
  268. .map_err(|e| network_error(e, format!("发送公钥请求失败: POST {}", url)))?;
  269. let response_text = response.text().await
  270. .map_err(|e| network_error(e, "读取公钥响应失败"))?;
  271. // 调试:打印后端原始响应(前 1024 字符)以定位解析错误
  272. {
  273. let prefix_len = std::cmp::min(1024, response_text.len());
  274. eprintln!("client response debug (prefix {}): {}", prefix_len, &response_text[..prefix_len]);
  275. }
  276. // 解析为通用 ApiResponse 形式
  277. let api_response_value: ApiResponse<serde_json::Value> = serde_json::from_str(&response_text)
  278. .map_err(|e| ClientError::SerializationError { source: e, operation: format!("解析公钥响应失败: {}", response_text) })?;
  279. if api_response_value.code != 200 {
  280. return Err(ClientError::ApiBusinessError {
  281. code: api_response_value.code,
  282. message: api_response_value.msg,
  283. });
  284. }
  285. // 取出加密字段
  286. let data_obj = api_response_value.data.ok_or(ClientError::ApiBusinessError {
  287. code: 500,
  288. message: "公钥响应缺失 data 字段".to_string(),
  289. })?;
  290. let encrypted_key_b64 = data_obj.get("encrypted_key").and_then(|v| v.as_str()).ok_or(ClientError::ApiBusinessError {
  291. code: 500,
  292. message: "公钥响应缺失 encrypted_key".to_string(),
  293. })?;
  294. let encrypted_data_b64 = data_obj.get("encrypted_data").and_then(|v| v.as_str()).ok_or(ClientError::ApiBusinessError {
  295. code: 500,
  296. message: "公钥响应缺失 encrypted_data".to_string(),
  297. })?;
  298. // Optional signature verification: server may include signature and signing_public_key (PEM)
  299. let signature_opt = data_obj.get("signature").and_then(|v| v.as_str());
  300. let signing_public_key_opt = data_obj.get("signing_public_key").and_then(|v| v.as_str());
  301. let timestamp_opt = data_obj.get("timestamp").and_then(|v| v.as_i64());
  302. let nonce_opt = data_obj.get("nonce").and_then(|v| v.as_str());
  303. // Client-side: 强制要求服务器返回签名与 signing_public_key (阶段性上线)
  304. if signature_opt.is_none() || signing_public_key_opt.is_none() {
  305. return Err(ClientError::ApiBusinessError { code: 400, message: "服务器未返回签名信息,拒绝响应(强制验签已启用)".to_string() });
  306. }
  307. // Verify signature; on failure, retry once by continuing loop
  308. if let (Some(sig_b64), Some(signing_pem)) = (signature_opt, signing_public_key_opt) {
  309. // Build signature input same as server: "{timestamp}:{nonce}:{base64(encrypted_data)}"
  310. let ts = timestamp_opt.unwrap_or(0);
  311. let nonce = nonce_opt.unwrap_or("");
  312. let signature_input = format!("{}:{}:{}", ts, nonce, encrypted_data_b64);
  313. match PKey::public_key_from_pem(signing_pem.as_bytes()) {
  314. Ok(pkey) => {
  315. let mut verifier = Verifier::new(MessageDigest::sha256(), &pkey)
  316. .map_err(|e| ClientError::UnknownError { message: format!("创建验签器失败: {}", e) })?;
  317. verifier.set_rsa_padding(Padding::PKCS1_PSS)
  318. .map_err(|e| ClientError::UnknownError { message: format!("设置RSA PSS填充失败: {}", e) })?;
  319. verifier.update(signature_input.as_bytes())
  320. .map_err(|e| ClientError::UnknownError { message: format!("验签数据更新失败: {}", e) })?;
  321. let sig_bytes = general_purpose::STANDARD.decode(sig_b64)
  322. .map_err(|e| ClientError::UnknownError { message: format!("base64 decode signature failed: {}", e) })?;
  323. let ok = verifier.verify(&sig_bytes)
  324. .map_err(|e| ClientError::UnknownError { message: format!("验签调用失败: {}", e) })?;
  325. if !ok {
  326. last_err = Some(ClientError::ApiBusinessError { code: 400, message: "服务器签名验证失败".to_string() });
  327. // retry if first attempt
  328. if attempt == 0 {
  329. continue;
  330. } else {
  331. return Err(last_err.unwrap());
  332. }
  333. }
  334. }
  335. Err(_) => {
  336. // unable to parse signing key, proceed but warn
  337. eprintln!("Warning: failed to parse signing_public_key PEM, skipping signature verification");
  338. }
  339. }
  340. }
  341. // if signature verified (or skipped), break loop to continue processing
  342. // proceed to decrypt below using encrypted_key_b64 / encrypted_data_b64
  343. let encrypted_key_bytes = general_purpose::STANDARD.decode(encrypted_key_b64)
  344. .map_err(|e| ClientError::UnknownError { message: format!("base64 解码 encrypted_key 失败: {}", e) })?;
  345. eprintln!(
  346. "[fetch_public_key] 准备解密 encrypted_key: encrypted_key_b64_len={} decoded_len={} aes_key_len={} iv_len=16",
  347. encrypted_key_b64.len(),
  348. encrypted_key_bytes.len(),
  349. aes_key.len()
  350. );
  351. if encrypted_key_bytes.len() % 16 != 0 {
  352. eprintln!("[fetch_public_key] 警告: encrypted_key_bytes 长度不是 16 的倍数,CBC 可能失败");
  353. }
  354. // openssl decrypt (key=aes_key[0..32], iv=aes_key[16..32],与后端 key_c=client_aes[:32], iv_c=client_aes[16:32] 一致)
  355. let response_key_iv = openssl::symm::decrypt(
  356. OpenSSLCipher::aes_256_cbc(),
  357. &aes_key,
  358. Some(&aes_key[16..32]),
  359. &encrypted_key_bytes,
  360. ).map_err(|e| {
  361. eprintln!(
  362. "[fetch_public_key] 解密 encrypted_key 失败: err={:?} encrypted_key_bytes_len={} aes_key_hex_prefix={:02x?}",
  363. e,
  364. encrypted_key_bytes.len(),
  365. &aes_key[..8.min(aes_key.len())]
  366. );
  367. aes_error(format!("解密 encrypted_key 失败: {}", e))
  368. })?;
  369. if response_key_iv.len() < 48 {
  370. return Err(ClientError::ApiBusinessError {
  371. code: 500,
  372. message: "解密后的 key_iv 长度异常".to_string(),
  373. });
  374. }
  375. let response_aes_key = &response_key_iv[0..32];
  376. let response_iv = &response_key_iv[32..48];
  377. // 5) 解析 encrypted_data -> decrypted_str (reuse existing code flow)
  378. let encrypted_data_bytes = general_purpose::STANDARD.decode(encrypted_data_b64)
  379. .map_err(|e| ClientError::UnknownError { message: format!("base64 解码 encrypted_data 失败: {}", e) })?;
  380. let decrypted_data_bytes = openssl::symm::decrypt(
  381. OpenSSLCipher::aes_256_cbc(),
  382. response_aes_key,
  383. Some(response_iv),
  384. &encrypted_data_bytes,
  385. ).map_err(|e| aes_error(format!("解密 encrypted_data 失败: {}", e)))?;
  386. let decrypted_str = String::from_utf8(decrypted_data_bytes)
  387. .map_err(|e| ClientError::UnknownError { message: format!("UTF8 解码失败: {}", e) })?;
  388. #[derive(Deserialize)]
  389. struct InnerPublicKey {
  390. public_key: String,
  391. #[serde(default)]
  392. key_version: Option<i32>,
  393. #[serde(default)]
  394. signing_public_key: Option<String>,
  395. }
  396. let public_key_data: InnerPublicKey = serde_json::from_str(&decrypted_str)
  397. .map_err(|e| ClientError::SerializationError { source: e, operation: format!("解析解密后的公钥 JSON 失败: {}", decrypted_str) })?;
  398. // 6) 解析 RSA 公钥
  399. let public_key = match RsaPublicKey::from_public_key_pem(&public_key_data.public_key) {
  400. Ok(pk) => pk,
  401. Err(_) => {
  402. RsaPublicKey::from_pkcs1_pem(&public_key_data.public_key)
  403. .map_err(|e| ClientError::RsaError { message: format!("RSA公钥解析失败: {}", e) })?
  404. }
  405. };
  406. // 缓存并记录版本
  407. if let Some(v) = public_key_data.key_version {
  408. self.current_key_version = Some(v);
  409. }
  410. self.public_key = Some(public_key.clone());
  411. // 同步到 key_storage,使 secure_heartbeat / secure_user_login 等使用同一套密钥,避免登出后再登录因密钥版本过期失败
  412. let kv = public_key_data.key_version.unwrap_or(1);
  413. crate::key_storage::store_rsa_key_segments(public_key_data.public_key.clone(), kv);
  414. return Ok(public_key);
  415. } // end retry loop
  416. // if here, return last_err or generic error
  417. if let Some(err) = last_err {
  418. return Err(err);
  419. } else {
  420. return Err(ClientError::ApiBusinessError { code: 500, message: "未知的握手失败".to_string() });
  421. }
  422. }
  423. // RSA+AES混合加密
  424. fn encrypt_request_data(&self, data: serde_json::Value, public_key: &RsaPublicKey) -> Result<String, Box<dyn std::error::Error>> {
  425. // 生成随机AES密钥和IV
  426. let mut rng = OsRng;
  427. let mut aes_key: [u8; 32] = [0u8; 32];
  428. rng.fill_bytes(&mut aes_key);
  429. let mut iv: [u8; 16] = [0u8; 16];
  430. rng.fill_bytes(&mut iv);
  431. // JSON序列化
  432. let json_str = serde_json::to_string(&data)?;
  433. let plaintext = json_str.as_bytes();
  434. // AES-CBC 加密(使用 OpenSSL,保证与后端兼容的 PKCS7 填充)
  435. let ciphertext = encrypt(
  436. OpenSSLCipher::aes_256_cbc(),
  437. &aes_key,
  438. Some(&iv),
  439. plaintext,
  440. ).map_err(|e| format!("AES encrypt failed: {}", e))?;
  441. // 使用RSA加密AES密钥
  442. let padding = Oaep::new::<Sha256>();
  443. let encrypted_aes_key = public_key.encrypt(&mut rng, padding, &aes_key)
  444. .map_err(|e| format!("Failed to encrypt AES key: {}", e))?;
  445. // 组合:加密的AES密钥(256字节) + IV(16字节) + 加密的数据
  446. let mut result = Vec::new();
  447. result.extend_from_slice(&encrypted_aes_key);
  448. result.extend_from_slice(&iv);
  449. result.extend_from_slice(&ciphertext);
  450. // 发送前调试日志(记录各段长度和 base64 前缀,便于后端对比)
  451. {
  452. let total_len = result.len();
  453. let enc_key_len = encrypted_aes_key.len();
  454. let iv_len = iv.len();
  455. let payload_len = ciphertext.len();
  456. // 输出到 stderr,便于在控制台/日志中查看
  457. eprintln!("client encrypt debug: total_len={}, enc_key_len={}, iv_len={}, payload_len={}", total_len, enc_key_len, iv_len, payload_len);
  458. }
  459. // Base64编码
  460. let encoded = general_purpose::STANDARD.encode(result);
  461. // 输出 base64 前缀(最多 120 字符),避免泄露全部密文
  462. {
  463. let prefix_len = std::cmp::min(120, encoded.len());
  464. eprintln!("client encrypt debug: base64_prefix={}", &encoded[..prefix_len]);
  465. }
  466. Ok(encoded)
  467. }
  468. // 解密响应数据
  469. fn decrypt_response_data(&self, encrypted_data: &str) -> Result<serde_json::Value, Box<dyn std::error::Error>> {
  470. let json_str = general_purpose::STANDARD.decode(encrypted_data)?;
  471. let json_str = String::from_utf8(json_str)?;
  472. Ok(serde_json::from_str(&json_str)?)
  473. }
  474. /// 处理带签名的安全响应
  475. ///
  476. /// 新的响应格式包含:
  477. /// - encrypted_data: AES加密的响应数据
  478. /// - timestamp: 响应时间戳
  479. /// - nonce: 响应随机字符串
  480. /// - signature: HMAC-SHA256签名
  481. /// - key_version: 密钥版本
  482. fn decrypt_secure_response<T: for<'de> serde::Deserialize<'de>>(
  483. &self,
  484. response_value: &serde_json::Value,
  485. ) -> Result<ApiResponse<T>, ClientError> {
  486. // 提取签名响应字段
  487. let encrypted_data = match response_value.get("encrypted_data") {
  488. Some(serde_json::Value::String(s)) => s.clone(),
  489. _ => {
  490. // 如果没有 encrypted_data,尝试从 data 字段获取(兼容旧格式)
  491. if let Some(data) = response_value.get("data") {
  492. if let Some(s) = data.as_str() {
  493. return self.decrypt_secure_response_string::<T>(s, response_value);
  494. }
  495. // 直接解析为 T
  496. let result: T = serde_json::from_value(data.clone())
  497. .map_err(|e| serialization_error(e, "解析响应数据"))?;
  498. return Ok(ApiResponse {
  499. code: response_value.get("code").and_then(|c| c.as_i64()).unwrap_or(200) as i32,
  500. msg: response_value.get("msg").and_then(|m| m.as_str()).unwrap_or("成功").to_string(),
  501. data: Some(result),
  502. });
  503. }
  504. return Err(ClientError::UnknownError {
  505. message: "响应中缺少 encrypted_data 字段".to_string(),
  506. });
  507. }
  508. };
  509. // 解密响应数据
  510. let decrypted_value = self.decrypt_response_data(&encrypted_data)
  511. .map_err(|e| aes_error(format!("响应数据解密失败: {}", e)))?;
  512. let result: T = serde_json::from_value(decrypted_value.clone())
  513. .map_err(|e| serialization_error(e, "解析解密后的数据"))?;
  514. // 提取原始响应信息
  515. let code = response_value.get("code").and_then(|c| c.as_i64()).unwrap_or(200) as i32;
  516. let msg = response_value.get("msg").and_then(|m| m.as_str()).unwrap_or("成功").to_string();
  517. Ok(ApiResponse {
  518. code,
  519. msg,
  520. data: Some(result),
  521. })
  522. }
  523. /// 处理带签名的安全响应(字符串格式)
  524. fn decrypt_secure_response_string<T: for<'de> serde::Deserialize<'de>>(
  525. &self,
  526. encrypted_data: &str,
  527. original_response: &serde_json::Value,
  528. ) -> Result<ApiResponse<T>, ClientError> {
  529. let decrypted_value = self.decrypt_response_data(encrypted_data)
  530. .map_err(|e| aes_error(format!("响应数据解密失败: {}", e)))?;
  531. let result: T = serde_json::from_value(decrypted_value)
  532. .map_err(|e| serialization_error(e, "解析解密后的数据"))?;
  533. let code = original_response.get("code").and_then(|c| c.as_i64()).unwrap_or(200) as i32;
  534. let msg = original_response.get("msg").and_then(|m| m.as_str()).unwrap_or("成功").to_string();
  535. Ok(ApiResponse {
  536. code,
  537. msg,
  538. data: Some(result),
  539. })
  540. }
  541. async fn make_request<T: for<'de> Deserialize<'de>>(
  542. &mut self,
  543. method: reqwest::Method,
  544. endpoint: &str,
  545. data: Option<serde_json::Value>,
  546. ) -> Result<ApiResponse<T>, ClientError> {
  547. let url = format!("{}{}", self.config.base_url, endpoint);
  548. log::info!("[make_request] {} {} (has_cached_pubkey={})", method, endpoint, self.public_key.is_some());
  549. // 获取(或从缓存)公钥
  550. let public_key = self.fetch_public_key().await?;
  551. // 准备请求数据
  552. let mut request_data = data.unwrap_or(serde_json::json!({}));
  553. request_data["software_code"] = self.config.software_code.clone().into();
  554. // 如果有session_id,添加到请求数据中
  555. if let Some(session_id) = &self.session_id {
  556. request_data["session_id"] = session_id.clone().into();
  557. }
  558. let encrypted_data = self.encrypt_request_data(request_data, &public_key)
  559. .map_err(|e| rsa_error(format!("请求数据加密失败: {}", e)))?;
  560. // 获取当前使用的密钥版本
  561. let key_version = self.current_key_version.unwrap_or(1);
  562. let request = self.client
  563. .request(method.clone(), &url)
  564. .header("Content-Type", "application/json")
  565. // include session id so backend dependencies can validate before decrypting body
  566. .header("X-Session-ID", match &self.session_id { Some(sid) => sid.clone(), None => "".to_string() })
  567. // include user hint headers when available; backend will validate these against session/token
  568. .header("X-User-Id", match self.current_user_id { Some(id) => id.to_string(), None => "".to_string() })
  569. .header("X-User-Name", match &self.current_username { Some(name) => name.clone(), None => "".to_string() })
  570. .json(&serde_json::json!({
  571. "encrypted": encrypted_data,
  572. "key_version": key_version
  573. }));
  574. let response = request.send().await
  575. .map_err(|e| network_error(e, format!("发送请求失败: {} {}", method, endpoint)))?;
  576. let status = response.status();
  577. if !status.is_success() {
  578. let error_text = response.text().await.unwrap_or_default();
  579. return Err(ClientError::ServerError {
  580. status: status.as_u16(),
  581. message: format!("HTTP {}: {}", status, error_text),
  582. });
  583. }
  584. let response_text = response.text().await
  585. .map_err(|e| network_error(e, "读取响应失败"))?;
  586. // 先解析为通用 Value 形式,兼容两种后端返回:
  587. // 1) ApiResponse.data 是加密后的字符串(String)
  588. // 2) ApiResponse.data 是直接的 JSON 对象(map)
  589. let api_response_value: ApiResponse<serde_json::Value> = serde_json::from_str(&response_text)
  590. .map_err(|e| serialization_error(e, "解析API响应"))?;
  591. if api_response_value.code != 200 {
  592. return Err(ClientError::ApiBusinessError {
  593. code: api_response_value.code,
  594. message: api_response_value.msg,
  595. });
  596. }
  597. if let Some(raw_data) = api_response_value.data {
  598. match raw_data {
  599. // 情况 A:后端返回加密的字符串(base64),需要解密后反序列化为 T
  600. serde_json::Value::String(encrypted_str) => {
  601. let decrypted_value = self.decrypt_response_data(&encrypted_str)
  602. .map_err(|e| aes_error(format!("响应数据解密失败: {}", e)))?;
  603. let result: T = serde_json::from_value(decrypted_value)
  604. .map_err(|e| serialization_error(e, "解析解密后的数据"))?;
  605. Ok(ApiResponse {
  606. code: api_response_value.code,
  607. msg: api_response_value.msg,
  608. data: Some(result),
  609. })
  610. }
  611. // 情况 B:后端直接返回 JSON 对象,直接转换为 T
  612. other => {
  613. let result: T = serde_json::from_value(other)
  614. .map_err(|e| serialization_error(e, "解析未加密响应数据"))?;
  615. Ok(ApiResponse {
  616. code: api_response_value.code,
  617. msg: api_response_value.msg,
  618. data: Some(result),
  619. })
  620. }
  621. }
  622. } else {
  623. Ok(ApiResponse {
  624. code: api_response_value.code,
  625. msg: api_response_value.msg,
  626. data: None,
  627. })
  628. }
  629. }
  630. // 用户相关API
  631. pub async fn register(&mut self, username: &str, password: &str, email: &str, card_code: &str, machine_code: &str) -> Result<ApiResponse<UserInfo>, ClientError> {
  632. let data = serde_json::json!({
  633. "username": username,
  634. "password": password,
  635. "email": email,
  636. "card_code": card_code,
  637. "machine_code": machine_code
  638. });
  639. self.make_plaintext_request(reqwest::Method::POST, "/api/user/register", Some(data)).await
  640. }
  641. pub async fn login(&mut self, username: &str, password: &str, machine_code: &str) -> Result<ApiResponse<UserInfo>, ClientError> {
  642. let data = serde_json::json!({
  643. "username": username,
  644. "password": password,
  645. "machine_code": machine_code
  646. });
  647. let result: ApiResponse<UserInfo> = self.make_plaintext_request(reqwest::Method::POST, "/api/user/login", Some(data)).await?;
  648. // 如果登录成功,设置session_id
  649. if result.code == 200 {
  650. if let Some(user_info) = &result.data {
  651. if let Some(session_id) = &user_info.session_id {
  652. self.set_session_id(session_id.clone());
  653. }
  654. // set current user id / username for header propagation
  655. if let Some(uid) = user_info.id {
  656. self.current_user_id = Some(uid);
  657. }
  658. self.current_username = Some(user_info.username.clone());
  659. }
  660. }
  661. Ok(result)
  662. }
  663. pub async fn unbind(&mut self, username: &str, password: &str) -> Result<ApiResponse<serde_json::Value>, ClientError> {
  664. let data = serde_json::json!({
  665. "username": username,
  666. "password": password
  667. });
  668. self.make_plaintext_request(reqwest::Method::POST, "/api/user/unbind", Some(data)).await
  669. }
  670. pub async fn recharge(&mut self, username: &str, password: &str, card_code: &str) -> Result<ApiResponse<serde_json::Value>, ClientError> {
  671. let data = serde_json::json!({
  672. "username": username,
  673. "password": password,
  674. "cardCode": card_code
  675. });
  676. self.make_plaintext_request(reqwest::Method::POST, "/api/user/recharge", Some(data)).await
  677. }
  678. pub async fn heartbeat(&mut self, user_id: i32) -> Result<ApiResponse<serde_json::Value>, ClientError> {
  679. let data = serde_json::json!({
  680. "user_id": user_id
  681. });
  682. self.make_request(reqwest::Method::POST, "/api/user/heartbeat", Some(data)).await
  683. }
  684. /// 登出:加密请求(make_request),与其它接口一致;依赖公钥缓存或握手。
  685. pub async fn logout(&mut self, user_id: i32, session_id: &str) -> Result<ApiResponse<serde_json::Value>, ClientError> {
  686. log::info!("[ApiClient] logout: user_id={} session_id_len={}", user_id, session_id.len());
  687. let data = serde_json::json!({
  688. "user_id": user_id,
  689. "session_id": session_id
  690. });
  691. self.make_request(reqwest::Method::POST, "/api/v1/auth/logout", Some(data)).await
  692. }
  693. #[allow(dead_code)]
  694. pub async fn validate_session(&mut self, session_id: &str) -> Result<ApiResponse<serde_json::Value>, ClientError> {
  695. let data = serde_json::json!({
  696. "session_id": session_id
  697. });
  698. self.make_request(reqwest::Method::POST, "/api/user/validate-session", Some(data)).await
  699. }
  700. pub async fn activate_card(&mut self, user_id: i32, card_code: &str) -> Result<ApiResponse<serde_json::Value>, ClientError> {
  701. let data = serde_json::json!({
  702. "user_id": user_id,
  703. "card_code": card_code
  704. });
  705. self.make_request(reqwest::Method::POST, "/api/user/activate-card", Some(data)).await
  706. }
  707. // Steam账号相关API
  708. pub async fn get_steam_account_limit(&mut self, user_id: i32) -> Result<ApiResponse<SteamAccountLimitData>, ClientError> {
  709. let data = serde_json::json!({
  710. "user_id": user_id
  711. });
  712. self.make_request(reqwest::Method::POST, "/api/v1/steam/account-limit", Some(data)).await
  713. }
  714. pub async fn get_steam_accounts(&mut self, user_id: i32) -> Result<ApiResponse<Vec<SteamAccount>>, ClientError> {
  715. let data = serde_json::json!({
  716. "user_id": user_id
  717. });
  718. self.make_request(reqwest::Method::POST, "/api/v1/steam/accounts/list", Some(data)).await
  719. }
  720. pub async fn create_steam_account(&mut self, user_id: i32, steam_username: &str, steam_id: Option<&str>) -> Result<ApiResponse<SteamAccount>, ClientError> {
  721. let data = serde_json::json!({
  722. "user_id": user_id,
  723. "steam_username": steam_username,
  724. "steam_id": steam_id
  725. });
  726. self.make_request(reqwest::Method::POST, "/api/v1/steam/accounts", Some(data)).await
  727. }
  728. pub async fn bind_steam_account(&mut self, user_id: i32, steam_username: &str, steam_id: &str) -> Result<ApiResponse<SteamAccount>, ClientError> {
  729. let data = serde_json::json!({
  730. "user_id": user_id,
  731. "steam_username": steam_username,
  732. "steam_id": steam_id
  733. });
  734. self.make_request(reqwest::Method::POST, "/api/v1/steam/accounts/bind", Some(data)).await
  735. }
  736. pub async fn update_steam_account(&mut self, user_id: i32, account_id: i32, updates: serde_json::Value) -> Result<ApiResponse<SteamAccount>, ClientError> {
  737. let mut data = updates;
  738. data["user_id"] = user_id.into();
  739. self.make_request(reqwest::Method::PUT, &format!("/api/v1/steam/accounts/{}", account_id), Some(data)).await
  740. }
  741. pub async fn delete_steam_account(&mut self, user_id: i32, account_id: i32) -> Result<ApiResponse<serde_json::Value>, ClientError> {
  742. let data = serde_json::json!({
  743. "user_id": user_id,
  744. "account_id": account_id
  745. });
  746. self.make_request(reqwest::Method::DELETE, "/api/v1/steam/accounts", Some(data)).await
  747. }
  748. // 公告相关API
  749. pub async fn get_announcements(&mut self, page: i32, page_size: i32, keyword: Option<&str>) -> Result<ApiResponse<Vec<Announcement>>, ClientError> {
  750. let mut params = HashMap::new();
  751. params.insert("page".to_string(), page.to_string());
  752. params.insert("page_size".to_string(), page_size.to_string());
  753. if let Some(kw) = keyword {
  754. params.insert("keyword".to_string(), kw.to_string());
  755. }
  756. let query_string = params.iter()
  757. .map(|(k, v)| format!("{}={}", k, v))
  758. .collect::<Vec<_>>()
  759. .join("&");
  760. let endpoint = format!("/api/v1/announcements?{}", query_string);
  761. // 公告接口不加密,直接调用
  762. let url = format!("{}{}", self.config.base_url, endpoint);
  763. let response = self.client.get(&url).send().await?;
  764. let response_text = response.text().await?;
  765. let api_response: ApiResponse<Vec<Announcement>> = serde_json::from_str(&response_text)?;
  766. Ok(api_response)
  767. }
  768. // 健康检查API
  769. pub async fn health_check(&self) -> Result<ApiResponse<serde_json::Value>, ClientError> {
  770. let url = format!("{}/api/v1/health", self.config.base_url);
  771. let response = self.client.get(&url).send().await?;
  772. let response_text = response.text().await?;
  773. let api_response: ApiResponse<serde_json::Value> = serde_json::from_str(&response_text)?;
  774. Ok(api_response)
  775. }
  776. // 明文请求方法(用于不需要加密的接口)
  777. async fn make_plaintext_request<T: for<'de> Deserialize<'de>>(
  778. &self,
  779. method: reqwest::Method,
  780. endpoint: &str,
  781. data: Option<serde_json::Value>,
  782. ) -> Result<ApiResponse<T>, ClientError> {
  783. let url = format!("{}{}", self.config.base_url, endpoint);
  784. let mut request = self.client
  785. .request(method.clone(), &url)
  786. .header("Content-Type", "application/json");
  787. // 如果有数据,添加到请求体中
  788. if let Some(request_data) = data {
  789. request = request.json(&request_data);
  790. }
  791. let response = request.send().await
  792. .map_err(|e| network_error(e, format!("发送明文请求失败: {} {}", method, endpoint)))?;
  793. let status = response.status();
  794. if !status.is_success() {
  795. let error_text = response.text().await.unwrap_or_default();
  796. return Err(ClientError::ServerError {
  797. status: status.as_u16(),
  798. message: format!("HTTP {}: {}", status, error_text),
  799. });
  800. }
  801. let response_text = response.text().await
  802. .map_err(|e| network_error(e, "读取明文响应失败"))?;
  803. let api_response: ApiResponse<T> = serde_json::from_str(&response_text)
  804. .map_err(|e| ClientError::SerializationError {
  805. source: e,
  806. operation: format!("解析明文响应失败: {}", response_text)
  807. })?;
  808. Ok(api_response)
  809. }
  810. // 公钥相关API
  811. pub async fn get_public_key(&self) -> Result<ApiResponse<PublicKeyData>, ClientError> {
  812. let url = format!("{}/api/v1/keys/public", self.config.base_url);
  813. let response = self.client.get(&url).send().await?;
  814. let response_text = response.text().await?;
  815. let api_response: ApiResponse<PublicKeyData> = serde_json::from_str(&response_text)?;
  816. Ok(api_response)
  817. }
  818. pub async fn get_client_configs(&mut self) -> Result<ApiResponse<serde_json::Value>, ClientError> {
  819. use base64::{Engine as _, engine::general_purpose};
  820. use openssl::symm::decrypt as openssl_decrypt;
  821. use openssl::symm::Cipher as OpenSSLCipher;
  822. use std::time::{SystemTime, UNIX_EPOCH};
  823. // 1) Generate a random AES key (32 bytes) and build handshake request
  824. let mut rng = OsRng;
  825. let mut aes_key: [u8; 32] = [0u8; 32];
  826. rng.fill_bytes(&mut aes_key);
  827. let aes_key_b64 = general_purpose::STANDARD.encode(&aes_key);
  828. let timestamp = SystemTime::now()
  829. .duration_since(UNIX_EPOCH)
  830. .map_err(|e| ClientError::UnknownError { message: format!("获取时间戳失败: {}", e) })?
  831. .as_secs() as i64;
  832. let mut nonce_bytes: [u8; 16] = [0u8; 16];
  833. rng.fill_bytes(&mut nonce_bytes);
  834. let nonce = nonce_bytes.iter().map(|b| format!("{:02x}", b)).collect::<String>();
  835. let request_body = serde_json::json!({
  836. "aes_key": aes_key_b64,
  837. "timestamp": timestamp,
  838. "nonce": nonce
  839. });
  840. // Retry handshake up to 2 attempts on signature verification failure
  841. let mut last_err_opt: Option<ClientError> = None;
  842. for attempt in 0..2 {
  843. let api_resp: ApiResponse<serde_json::Value> = self.make_plaintext_request(reqwest::Method::POST, "/api/configs", Some(request_body.clone())).await?;
  844. if api_resp.code != 200 {
  845. return Ok(ApiResponse {
  846. code: api_resp.code,
  847. msg: api_resp.msg,
  848. data: api_resp.data,
  849. });
  850. }
  851. let data_obj = api_resp.data.ok_or(ClientError::SerializationError {
  852. source: serde_json::Error::io(std::io::Error::new(std::io::ErrorKind::Other, "Missing data field in configs response")),
  853. operation: "parse configs response".to_string(),
  854. })?;
  855. // Extract fields
  856. let encrypted_key_b64 = data_obj.get("encrypted_key").and_then(|v| v.as_str()).ok_or(ClientError::SerializationError {
  857. source: serde_json::Error::io(std::io::Error::new(std::io::ErrorKind::Other, "missing encrypted_key")),
  858. operation: "configs response".to_string(),
  859. })?;
  860. let encrypted_data_b64 = data_obj.get("encrypted_data").and_then(|v| v.as_str()).ok_or(ClientError::SerializationError {
  861. source: serde_json::Error::io(std::io::Error::new(std::io::ErrorKind::Other, "missing encrypted_data")),
  862. operation: "configs response".to_string(),
  863. })?;
  864. // signature fields
  865. let signature_opt = data_obj.get("signature").and_then(|v| v.as_str());
  866. let signing_public_key_opt = data_obj.get("signing_public_key").and_then(|v| v.as_str());
  867. let timestamp_opt = data_obj.get("timestamp").and_then(|v| v.as_i64());
  868. let nonce_opt = data_obj.get("nonce").and_then(|v| v.as_str());
  869. if signature_opt.is_none() || signing_public_key_opt.is_none() {
  870. return Ok(ApiResponse { code: 400, msg: "服务器未返回签名信息,握手失败".to_string(), data: None });
  871. }
  872. let sig_b64 = signature_opt.unwrap();
  873. let signing_pem = signing_public_key_opt.unwrap();
  874. let ts = timestamp_opt.unwrap_or(0);
  875. let nonce_s = nonce_opt.unwrap_or("");
  876. let signature_input = format!("{}:{}:{}", ts, nonce_s, encrypted_data_b64);
  877. // verify signature
  878. let verify_ok = match PKey::public_key_from_pem(signing_pem.as_bytes()) {
  879. Ok(pkey) => {
  880. let mut verifier = Verifier::new(MessageDigest::sha256(), &pkey)
  881. .map_err(|e| ClientError::UnknownError { message: format!("创建验签器失败: {}", e) }).ok();
  882. if verifier.is_none() { false } else {
  883. let mut verifier = verifier.unwrap();
  884. if verifier.set_rsa_padding(Padding::PKCS1_PSS).is_err() { false } else {
  885. if verifier.update(signature_input.as_bytes()).is_err() { false } else {
  886. let sig_bytes = general_purpose::STANDARD.decode(sig_b64).map_err(|e| ClientError::UnknownError { message: format!("base64 decode signature failed: {}", e) }).ok();
  887. if sig_bytes.is_none() { false } else {
  888. verifier.verify(&sig_bytes.unwrap()).map_err(|e| ClientError::UnknownError { message: format!("验签调用失败: {}", e) }).unwrap_or(false)
  889. }
  890. }
  891. }
  892. }
  893. }
  894. Err(_) => {
  895. eprintln!("Warning: failed to parse signing_public_key PEM, skipping signature verification");
  896. true
  897. }
  898. };
  899. if !verify_ok {
  900. last_err_opt = Some(ClientError::ApiBusinessError { code: 400, message: "服务器签名验证失败".to_string() });
  901. if attempt == 0 {
  902. // retry once
  903. continue;
  904. } else {
  905. return Err(last_err_opt.unwrap());
  906. }
  907. }
  908. // proceed to decrypt as before
  909. let encrypted_key_bytes = general_purpose::STANDARD.decode(encrypted_key_b64)
  910. .map_err(|e| ClientError::UnknownError { message: format!("base64 decode failed: {}", e) })?;
  911. let response_key_iv = openssl_decrypt(
  912. OpenSSLCipher::aes_256_cbc(),
  913. &aes_key,
  914. Some(&aes_key[16..32]),
  915. &encrypted_key_bytes,
  916. ).map_err(|e| ClientError::UnknownError { message: format!("decrypt encrypted_key failed: {}", e) })?;
  917. if response_key_iv.len() < 48 {
  918. return Err(ClientError::UnknownError { message: "decrypted key_iv length invalid".to_string() });
  919. }
  920. let response_aes_key = &response_key_iv[0..32];
  921. let response_iv = &response_key_iv[32..48];
  922. // 4) Decrypt encrypted_data using response_aes_key and response_iv (AES-CBC)
  923. let encrypted_data_bytes = general_purpose::STANDARD.decode(encrypted_data_b64)
  924. .map_err(|e| ClientError::UnknownError { message: format!("base64 decode failed: {}", e) })?;
  925. let decrypted_bytes = openssl_decrypt(
  926. OpenSSLCipher::aes_256_cbc(),
  927. response_aes_key,
  928. Some(response_iv),
  929. &encrypted_data_bytes,
  930. ).map_err(|e| ClientError::UnknownError { message: format!("decrypt encrypted_data failed: {}", e) })?;
  931. // Parse decrypted JSON payload
  932. let decrypted_value: serde_json::Value = serde_json::from_slice(&decrypted_bytes)
  933. .map_err(|e| ClientError::SerializationError { source: e, operation: "parse decrypted configs".to_string() })?;
  934. return Ok(ApiResponse {
  935. code: api_resp.code,
  936. msg: api_resp.msg,
  937. data: Some(decrypted_value),
  938. });
  939. }
  940. // no successful attempt
  941. if let Some(err) = last_err_opt {
  942. Err(err)
  943. } else {
  944. Err(ClientError::ApiBusinessError { code: 500, message: "未知的握手失败".to_string() })
  945. }
  946. }
  947. }
  948. // 全局API客户端实例
  949. lazy_static::lazy_static! {
  950. static ref API_CLIENT: std::sync::Mutex<Option<BackendApiClient>> = std::sync::Mutex::new(None);
  951. }
  952. // 全局共享的 reqwest Client(带连接池,减少 TCP 连接开销)
  953. lazy_static::lazy_static! {
  954. static ref HTTP_CLIENT: reqwest::Client = reqwest::Client::builder()
  955. .pool_max_idle_per_host(16) // 每个 host 最多保留 16 个空闲连接
  956. .pool_idle_timeout(std::time::Duration::from_secs(30)) // 空闲连接 30s 后释放
  957. .tcp_keepalive(std::time::Duration::from_secs(60)) // TCP keep-alive 60s
  958. .build()
  959. .expect("创建全局 HTTP 客户端失败");
  960. }
  961. /// 获取全局共享的 reqwest Client(带连接池)
  962. pub fn get_http_client() -> reqwest::Client {
  963. HTTP_CLIENT.clone()
  964. }
  965. pub fn get_api_client() -> Result<std::sync::MutexGuard<'static, Option<BackendApiClient>>, Box<dyn std::error::Error>> {
  966. Ok(API_CLIENT.lock().map_err(|e| format!("Failed to lock API client: {}", e))?)
  967. }
  968. pub fn initialize_api_client(config: ApiConfig) -> Result<(), ClientError> {
  969. let client = BackendApiClient::new(config)?;
  970. let mut guard = get_api_client().map_err(|e| ClientError::UnknownError {
  971. message: format!("获取API客户端锁失败: {}", e),
  972. })?;
  973. *guard = Some(client);
  974. Ok(())
  975. }
  976. // 获取API客户端的克隆版本(用于async函数)
  977. pub fn get_api_client_for_async() -> Result<BackendApiClient, ClientError> {
  978. let guard = get_api_client().map_err(|e| ClientError::UnknownError {
  979. message: format!("获取API客户端锁失败: {}", e),
  980. })?;
  981. if let Some(client) = guard.as_ref() {
  982. // 注意:这里我们克隆客户端,这不是最优的解决方案
  983. // 在生产环境中,应该使用Arc<Mutex<>>或其他并发安全的解决方案
  984. Ok(BackendApiClient {
  985. client: client.client.clone(),
  986. config: client.config.clone(),
  987. public_key: client.public_key.clone(),
  988. public_keys: client.public_keys.clone(),
  989. key_order: client.key_order.clone(),
  990. current_key_version: client.current_key_version.clone(),
  991. session_id: client.session_id.clone(),
  992. current_user_id: client.current_user_id.clone(),
  993. current_username: client.current_username.clone(),
  994. })
  995. } else {
  996. Err(ClientError::ClientNotInitialized)
  997. }
  998. }