ios - iOS Swift 5 钥匙串状态 -50 错误 SecItemAdd
问题描述
我正在尝试按照教程编写一个包装器以进入Security
模块和Keychain
api。包装器似乎没问题,但是当我尝试将密码设置到钥匙串中时,出现状态号为 -50 的错误。
import Security
class SecureStore {
private func setupQueryDictionary(forKey key: String) throws -> [CFString: Any] {
guard let keyData = key.data(using: .utf8) else {
print("Error! Cannot convert the key to the expected format")
throw SecureStoreError.invalidContent
}
let query: [CFString: Any] = [kSecClass: kSecClassGenericPassword,
kSecAttrAccount: keyData]
return query
}
func set(entry: String, forKey key: String) throws {
guard !entry.isEmpty && !key.isEmpty else {
print("Cant add an empty string to the keychain")
throw SecureStoreError.queryEmptyWhenSet
}
try removeEntry(forKey: key)
var queryDictionary = try setupQueryDictionary(forKey: key)
queryDictionary[kSecClass] = entry.data(using: .utf8)
let status = SecItemAdd(queryDictionary as CFDictionary, nil)
guard status == errSecSuccess else {
print("status ==> ", status.description)
throw SecureStoreError.failureOnWrite(status)
}
}
func removeEntry(forKey key: String) throws {
guard !key.isEmpty else {
print("key must be valid")
throw SecureStoreError.queryEmptyWhenDelete
}
let queryDictionary = try setupQueryDictionary(forKey: key)
SecItemDelete(queryDictionary as CFDictionary)
}
func entry(forKey key: String) throws -> String? {
guard !key.isEmpty else {
print("key must be valid")
throw SecureStoreError.invalidContent
}
var queryDictionary = try setupQueryDictionary(forKey: key)
queryDictionary[kSecReturnData] = kCFBooleanTrue
queryDictionary[kSecMatchLimit] = kSecMatchLimitOne
var data: AnyObject?
let status = SecItemCopyMatching(queryDictionary as CFDictionary, &data)
guard status == errSecSuccess else {
print("status ==> ", status)
throw SecureStoreError.failureOnRead(status)
}
guard let itemData = data as? Data, let result = String(data: itemData, encoding: .utf8) else {
return nil
}
return result
}
}
enum SecureStoreError: Error {
case invalidContent
case queryEmptyWhenSet
case queryEmptyWhenDelete
case failureOnWrite(OSStatus)
case failureOnRead(OSStatus)
}
extension SecureStoreError: LocalizedError {
public var errorDescription: String? {
switch self {
case .invalidContent:
return NSLocalizedString("Cannot convert to the .utf8 format", comment: "")
case .queryEmptyWhenSet:
return NSLocalizedString("for set(:,:), parameters cannot be empty ", comment: "")
case .queryEmptyWhenDelete:
return NSLocalizedString("for removeEntry(:,:), parameters cannot be empty ", comment: "")
case .failureOnWrite(let status):
return NSLocalizedString("Error when write to keychain item \(status.description)", comment: "")
case .failureOnRead(let status):
return NSLocalizedString("Error when read to keychain item \(status.description)", comment: "")
}
}
}
Wrapper 对我来说似乎没问题,但我无法找到错误背后的真正问题。
我已经做了这些:
1- 在 Xcode 目标中添加功能并设置一个组。
2-在模拟器中尝试,得到同样的错误
3-我用主线程试过了,没有效果。
这是我的来电者:
let security = SecureStore.init()
do {
try security.set(entry: "myPassword12345.12345", forKey: "_passwordForFacebook")
let password = try security.entry(forKey: "_passwordForFacebook")
print("password > ", password )
} catch {
print("error > ", error.localizedDescription)
}
提前致谢。
解决方案
这可能是由于创建查询错误造成的。对于通用密码,该项目应如下所示:
let query = [
kSecClass: kSecClassGenericPasswor,
kSecAttrAccount: "_passwordForFacebook",
kSecAttrValueData: Data("myPassword12345.12345".utf8)
] as CFDictionary
目前,您正在将 设置kSecClass
为密码的值。
queryDictionary[kSecClass] = entry.data(using: .utf8) // <-- this is invalid
这应该可以为您解决该问题:
queryDictionary[kSecValueData] = entry.data(using: .utf8)
推荐阅读
- ios - 进一步自定义 safeAreaView
- java - 从数据库返回的对象列表为空
- python - urllib 或 stdlib 中是否有一个函数可以识别类似 SSH 的 URL 与本地路径?
- r - 从我每天收到的新数据框上的数据集中获取汇总统计数据的最佳方法?
- excel - 根据 ID 突出显示具有不同值的单元格
- php - PHP 退出状态码是什么?
- pandas - 如何使用 to_sql() 将包含 pd.Period 的 pandas Dataframe 上传到数据库
- javascript - 如何在 2D 字符数组中查找单词并返回 JS 中未使用的字符?
- java - Java - 以编程方式检查文件名中的无效字符
- c# - 从强类型视图回发 DropDownList