import Foundation import Security /// JWT 持久化(对应安卓的 EncryptedSharedPreferences)。Keychain 本身加密 + 系统托管密钥。 enum KeychainStore { enum Key: String { case accessToken = "access_token" case refreshToken = "refresh_token" } private static let service = "com.jishisongfu.shaguabijia.auth" static func get(_ key: Key) -> String? { let query: [String: Any] = [ kSecClass as String: kSecClassGenericPassword, kSecAttrService as String: service, kSecAttrAccount as String: key.rawValue, kSecReturnData as String: true, kSecMatchLimit as String: kSecMatchLimitOne, ] var item: CFTypeRef? guard SecItemCopyMatching(query as CFDictionary, &item) == errSecSuccess, let data = item as? Data, let str = String(data: data, encoding: .utf8) else { return nil } return str } static func set(_ value: String, _ key: Key) { let data = Data(value.utf8) let base: [String: Any] = [ kSecClass as String: kSecClassGenericPassword, kSecAttrService as String: service, kSecAttrAccount as String: key.rawValue, ] // upsert:先删再加,避免 duplicate item SecItemDelete(base as CFDictionary) var attrs = base attrs[kSecValueData as String] = data attrs[kSecAttrAccessible as String] = kSecAttrAccessibleAfterFirstUnlock SecItemAdd(attrs as CFDictionary, nil) } static func delete(_ key: Key) { let query: [String: Any] = [ kSecClass as String: kSecClassGenericPassword, kSecAttrService as String: service, kSecAttrAccount as String: key.rawValue, ] SecItemDelete(query as CFDictionary) } }