- Published on
Keychain β maxfiy ma'lumotlarni xavfsiz saqlash
- Authors
- Name
- ShoxruxC
- @iOSdasturchi
Parollar, API tokenlar, maxfiy kalitlar β bularni UserDefaults da saqlash XAVFLI. Keychain β Apple ning shifrlangan xavfsiz ombori.
Keychain Wrapper yaratish
import Foundation
import Security
// βββββββββββββββββββββββββββββββββββββββ
// KEYCHAIN MENEJERI β soddalashtirilgan API
// βββββββββββββββββββββββββββββββββββββββ
class KeychainMenejer {
// Saqlash
static func saqlash(kalit: String, ma'lumot: String) -> Bool {
// String ni Data ga aylantirish
guard let data = ma'lumot.data(using: .utf8) else { return false }
// Avval eski qiymatni o'chirish (yangilash uchun)
oChirish(kalit: kalit)
// Query β Keychain ga qanday saqlash
let query: [String: Any] = [
kSecClass as String: kSecClassGenericPassword,
kSecAttrAccount as String: kalit, // Kalit (identifikator)
kSecValueData as String: data, // Qiymat (shifrlangan)
]
// Keychain ga qo'shish
let status = SecItemAdd(query as CFDictionary, nil)
return status == errSecSuccess
}
// O'qish
static func olish(kalit: String) -> String? {
let query: [String: Any] = [
kSecClass as String: kSecClassGenericPassword,
kSecAttrAccount as String: kalit,
kSecReturnData as String: true, // Ma'lumotni qaytar
kSecMatchLimit as String: kSecMatchLimitOne, // Bitta natija
]
var natija: AnyObject?
let status = SecItemCopyMatching(query as CFDictionary, &natija)
guard status == errSecSuccess,
let data = natija as? Data,
let matn = String(data: data, encoding: .utf8)
else { return nil }
return matn
}
// O'chirish
@discardableResult
static func oChirish(kalit: String) -> Bool {
let query: [String: Any] = [
kSecClass as String: kSecClassGenericPassword,
kSecAttrAccount as String: kalit,
]
let status = SecItemDelete(query as CFDictionary)
return status == errSecSuccess
}
// Yangilash
static func yangilash(kalit: String, yangiMalumot: String) -> Bool {
guard let data = yangiMalumot.data(using: .utf8) else { return false }
let query: [String: Any] = [
kSecClass as String: kSecClassGenericPassword,
kSecAttrAccount as String: kalit,
]
let yangilanish: [String: Any] = [
kSecValueData as String: data,
]
let status = SecItemUpdate(
query as CFDictionary,
yangilanish as CFDictionary
)
return status == errSecSuccess
}
}
Ishlatish
// βββββββββββββββββββββββββββββββββββββββ
// AMALIY ISHLATISH
// βββββββββββββββββββββββββββββββββββββββ
// API token saqlash
KeychainMenejer.saqlash(kalit: "api_token", ma'lumot: "abc123xyz")
// Token o'qish
if let token = KeychainMenejer.olish(kalit: "api_token") {
print("Token: \(token)")
}
// Token yangilash
KeychainMenejer.yangilash(kalit: "api_token", yangiMalumot: "yangi_token_456")
// Token o'chirish (logout)
KeychainMenejer.oChirish(kalit: "api_token")
// βββββββββββββββββββββββββββββββββββββββ
// SWIFTUI BILAN ISHLATISH
// βββββββββββββββββββββββββββββββββββββββ
class AuthViewModel: ObservableObject {
@Published var tizimgaKirgan = false
init() {
// Ilova ochilganda token bor-yo'qligini tekshirish
tizimgaKirgan = KeychainMenejer.olish(kalit: "auth_token") != nil
}
func kirish(email: String, parol: String) async {
// Tarmoq so'rovi β token olish
let token = "server_dan_kelgan_token"
// β
Token ni Keychain da saqlash
KeychainMenejer.saqlash(kalit: "auth_token", ma'lumot: token)
await MainActor.run {
tizimgaKirgan = true
}
}
func chiqish() {
// β
Token ni Keychain dan o'chirish
KeychainMenejer.oChirish(kalit: "auth_token")
tizimgaKirgan = false
}
}
Nima qayerda saqlash kerak
| Ma'lumot | Saqlash joyi | Sabab |
|---|---|---|
| Parol, Token | β Keychain | Shifrlangan, xavfsiz |
| Foydalanuvchi sozlamalari | UserDefaults / @AppStorage | Maxfiy emas |
| Katta ma'lumot | SwiftData / CoreData | Tuzilgan ma'lumotlar bazasi |
| Fayllar | FileManager | Rasm, video, hujjat |
π― Topshiriq
AuthViewModel yarating: kirish(email:parol:), chiqish(), tokenBormi(). Keychain da "auth_token" saqlang. SwiftUI da login/logout ekran yarating β token bo'lsa asosiy ekran, bo'lmasa login.