wake-ios/wake/Utils/KeychainHelper.swift
2025-09-01 19:42:32 +08:00

116 lines
3.8 KiB
Swift
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

import Foundation
import Security
/// Keychain
public class KeychainHelper {
// Keychain
private enum KeychainKey: String, CaseIterable {
case accessToken = "com.memorywake.accessToken"
case refreshToken = "com.memorywake.refreshToken"
}
/// 访 Keychain
public static func saveAccessToken(_ token: String) -> Bool {
return save(token, for: .accessToken)
}
/// Keychain 访
public static func getAccessToken() -> String? {
return get(for: .accessToken)
}
/// Keychain
public static func saveRefreshToken(_ token: String) -> Bool {
return save(token, for: .refreshToken)
}
/// Keychain
public static func getRefreshToken() -> String? {
return get(for: .refreshToken)
}
///
public static func clearTokens() {
delete(for: .accessToken)
delete(for: .refreshToken)
}
/// Keychain
public static func clearAll() {
// keychain
KeychainKey.allCases.forEach { key in
delete(for: key)
}
//
let query: [String: Any] = [
kSecClass as String: kSecClassGenericPassword,
kSecReturnAttributes as String: true,
kSecMatchLimit as String: kSecMatchLimitAll
]
var result: AnyObject?
let status = SecItemCopyMatching(query as CFDictionary, &result)
if status == errSecSuccess, let items = result as? [[String: Any]] {
for item in items {
if let account = item[kSecAttrAccount as String] as? String,
let service = item[kSecAttrService as String] as? String {
let deleteQuery: [String: Any] = [
kSecClass as String: kSecClassGenericPassword,
kSecAttrAccount as String: account,
kSecAttrService as String: service
]
SecItemDelete(deleteQuery as CFDictionary)
}
}
}
}
// MARK: -
private static func save(_ string: String, for key: KeychainKey) -> Bool {
guard let data = string.data(using: .utf8) else { return false }
let query: [String: Any] = [
kSecClass as String: kSecClassGenericPassword,
kSecAttrAccount as String: key.rawValue,
kSecValueData as String: data
]
//
SecItemDelete(query as CFDictionary)
//
let status = SecItemAdd(query as CFDictionary, nil)
return status == errSecSuccess
}
private static func get(for key: KeychainKey) -> String? {
let query: [String: Any] = [
kSecClass as String: kSecClassGenericPassword,
kSecAttrAccount as String: key.rawValue,
kSecReturnData as String: true,
kSecMatchLimit as String: kSecMatchLimitOne
]
var dataTypeRef: AnyObject?
let status = SecItemCopyMatching(query as CFDictionary, &dataTypeRef)
guard status == errSecSuccess, let data = dataTypeRef as? Data else {
return nil
}
return String(data: data, encoding: .utf8)
}
private static func delete(for key: KeychainKey) {
let query: [String: Any] = [
kSecClass as String: kSecClassGenericPassword,
kSecAttrAccount as String: key.rawValue
]
SecItemDelete(query as CFDictionary)
}
}