Secure Enclave Keychain存储凭证成功但读取返回空字符串问题求解
排查修复步骤
1. 修复存储逻辑缺失的更新处理
当前storeCredentials方法仅支持新增凭证,若对应server下已存在旧凭证,调用SecItemAdd会直接返回errSecDuplicateItem错误,新的凭证不会被写入,你读到的就是旧的空值数据。
修改存储逻辑,先检查是否存在旧记录,存在则走更新逻辑,不存在再走新增:
static func storeCredentials(credentials: Credentials) { print("Storing user credentials...") let account = credentials.email let password = credentials.password.data(using: .utf8)! let baseQuery: [String: Any] = [kSecClass as String: kSecClassInternetPassword, kSecAttrServer as String: server] // 先查询是否已存在记录 let checkStatus = SecItemCopyMatching(baseQuery as CFDictionary, nil) if checkStatus == errSecSuccess { // 存在旧记录,执行更新 let updateAttr: [String: Any] = [kSecAttrAccount as String: account, kSecValueData as String: password] let updateStatus = SecItemUpdate(baseQuery as CFDictionary, updateAttr as CFDictionary) if updateStatus == errSecSuccess { print("Successfully updated credentials") } else { let errorMsg = SecCopyErrorMessageString(updateStatus, nil) as? String ?? "未知错误" print("更新凭证失败,错误码:\(updateStatus),错误信息:\(errorMsg)") } } else if checkStatus == errSecItemNotFound { // 不存在旧记录,执行新增 var addQuery = baseQuery addQuery[kSecAttrAccount as String] = account addQuery[kSecValueData as String] = password // 建议加上访问权限控制,避免后续读写异常 addQuery[kSecAttrAccessible as String] = kSecAttrAccessibleWhenUnlocked let addStatus = SecItemAdd(addQuery as CFDictionary, nil) if addStatus == errSecSuccess { print("Successfully added credentials") } else { let errorMsg = SecCopyErrorMessageString(addStatus, nil) as? String ?? "未知错误" print("新增凭证失败,错误码:\(addStatus),错误信息:\(errorMsg)") } } else { let errorMsg = SecCopyErrorMessageString(checkStatus, nil) as? String ?? "未知错误" print("查询旧凭证失败,错误码:\(checkStatus),错误信息:\(errorMsg)") } }
2. 修复读取逻辑的错误判断
当前读取代码的状态判断写反了,会干扰排查:
// 原错误逻辑:只要不是找不到凭证,就打印“无密码” if status != errSecItemNotFound { print("No Password") }
修改为正确的判断逻辑:
if status == errSecItemNotFound { print("No Password") } else if status != errSecSuccess { let errorMsg = SecCopyErrorMessageString(status, nil) as? String ?? "未知错误" print("读取凭证失败,错误码:\(status),错误信息:\(errorMsg)") }
3. 确认Keychain权限已开启
在Xcode项目设置的Signing & Capabilities标签页,添加Keychain Sharing能力,无需额外配置Keychain Group即可正常使用基础Keychain功能。如果未开启该能力,Keychain操作会返回errSecMissingEntitlement(错误码-25243)权限错误。
4. 清空历史脏数据测试
如果之前已经存入过空值凭证,可以新增清空方法先清除旧数据再测试:
static func clearOldCredentials() { let query: [String: Any] = [kSecClass as String: kSecClassInternetPassword, kSecAttrServer as String: server] SecItemDelete(query as CFDictionary) }
内容的提问来源于stack exchange,提问作者Saamer
相关产品推荐
相关产品推荐

