114 lines
		
	
	
		
			3.9 KiB
		
	
	
	
		
			Swift
		
	
	
	
	
	
			
		
		
	
	
			114 lines
		
	
	
		
			3.9 KiB
		
	
	
	
		
			Swift
		
	
	
	
	
	
import Foundation
 | 
						||
import Security
 | 
						||
 | 
						||
 | 
						||
//let username = "user1"
 | 
						||
 | 
						||
// Сохраняем токены
 | 
						||
//KeychainService.shared.save("access_token_value", forKey: "access_token", service: username)
 | 
						||
//KeychainService.shared.save("refresh_token_value", forKey: "refresh_token", service: username)
 | 
						||
 | 
						||
// Получаем токены
 | 
						||
//let accessToken = KeychainService.shared.get(forKey: "access_token", service: username)
 | 
						||
//let refreshToken = KeychainService.shared.get(forKey: "refresh_token", service: username)
 | 
						||
 | 
						||
// получение всех пользователей
 | 
						||
//let users = KeychainService.shared.getAllServices()
 | 
						||
//print("Все пользователи: \(users)")
 | 
						||
 | 
						||
// Удаление всех пользователей
 | 
						||
//KeychainService.shared.deleteAll()
 | 
						||
 | 
						||
// удаление по одному
 | 
						||
//KeychainService.shared.delete(forKey: "access_token", service: username)
 | 
						||
//KeychainService.shared.delete(forKey: "refresh_token", service: username)
 | 
						||
 | 
						||
 | 
						||
class KeychainService {
 | 
						||
    
 | 
						||
    static let shared = KeychainService()
 | 
						||
    
 | 
						||
    private init() {}
 | 
						||
    
 | 
						||
    func save(_ value: String, forKey key: String, service: String) {
 | 
						||
        guard let data = value.data(using: .utf8) else { return }
 | 
						||
        
 | 
						||
        let query: [String: Any] = [
 | 
						||
            kSecClass as String: kSecClassGenericPassword,
 | 
						||
            kSecAttrService as String: service, // ключ группировки
 | 
						||
            kSecAttrAccount as String: key,
 | 
						||
            kSecValueData as String: data
 | 
						||
        ]
 | 
						||
        
 | 
						||
        SecItemDelete(query as CFDictionary)
 | 
						||
        let status = SecItemAdd(query as CFDictionary, nil)
 | 
						||
        if status != errSecSuccess {
 | 
						||
            print("Error saving to Keychain: \(status)")
 | 
						||
        }
 | 
						||
    }
 | 
						||
    
 | 
						||
    func get(forKey key: String, service: String) -> String? {
 | 
						||
        let query: [String: Any] = [
 | 
						||
            kSecClass as String: kSecClassGenericPassword,
 | 
						||
            kSecAttrService as String: service,
 | 
						||
            kSecAttrAccount as String: key,
 | 
						||
            kSecReturnData as String: true,
 | 
						||
            kSecMatchLimit as String: kSecMatchLimitOne
 | 
						||
        ]
 | 
						||
        
 | 
						||
        var dataTypeRef: AnyObject?
 | 
						||
        let status = SecItemCopyMatching(query as CFDictionary, &dataTypeRef)
 | 
						||
        if status == errSecSuccess,
 | 
						||
           let data = dataTypeRef as? Data,
 | 
						||
           let value = String(data: data, encoding: .utf8) {
 | 
						||
            return value
 | 
						||
        }
 | 
						||
        return nil
 | 
						||
    }
 | 
						||
    
 | 
						||
    func getAllServices() -> [String] {
 | 
						||
        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)
 | 
						||
        
 | 
						||
        guard status == errSecSuccess, let items = result as? [[String: Any]] else {
 | 
						||
            return []
 | 
						||
        }
 | 
						||
        
 | 
						||
        // Собираем все уникальные service (username)
 | 
						||
        var services = Set<String>()
 | 
						||
        for item in items {
 | 
						||
            if let service = item[kSecAttrService as String] as? String {
 | 
						||
                services.insert(service)
 | 
						||
            }
 | 
						||
        }
 | 
						||
        
 | 
						||
        return Array(services)
 | 
						||
    }
 | 
						||
    
 | 
						||
    func delete(forKey key: String, service: String) {
 | 
						||
        let query: [String: Any] = [
 | 
						||
            kSecClass as String: kSecClassGenericPassword,
 | 
						||
            kSecAttrService as String: service,
 | 
						||
            kSecAttrAccount as String: key
 | 
						||
        ]
 | 
						||
        SecItemDelete(query as CFDictionary)
 | 
						||
    }
 | 
						||
    
 | 
						||
    /// Удалить все записи Keychain, сохранённые этим приложением
 | 
						||
    func deleteAll() {
 | 
						||
        let query: [String: Any] = [
 | 
						||
            kSecClass as String: kSecClassGenericPassword
 | 
						||
        ]
 | 
						||
        let status = SecItemDelete(query as CFDictionary)
 | 
						||
        if status != errSecSuccess && status != errSecItemNotFound {
 | 
						||
            print("Error deleting all Keychain items: \(status)")
 | 
						||
        }
 | 
						||
    }
 | 
						||
}
 |