Table of Contents
Pengantar Ofeksi untuk Penyimpanan Data Teraman di iOS
Memproteksi data pengguna sensitif merupakan tanggung jawab fundamental dari aplikasi iOS manapun. Apakah Anda menyimpan token otentikasi, kunci enkripsi, atau kelayakan pribadi, platform menyediakan solusi yang didedikasi yang didukung-kembali perangkat keras: Keychain. Tidak seperti atau berkas daftar properti, Keychain mengenkripsi data di istirahat dan menegakkan kontrol akses yang ketat. Artikel ini menyediakan panduan komprehensif untuk menerapkan penyimpanan data aman dengan Keychain, meliputi baik kerangka kerja keamanan asli dan praktik praktis terbaik untuk aplikasi produksi.
Memahami rantai kunci iOS
Kunci Kunci Kunci adalah wadah penyimpanan aman yang dikelola oleh sistem operasi. Ini menyimpan barang-barang kecil yang sensitif ⁇ seperti sandi, kunci kriptografi, atau sertifikat ⁇ dalam database terenkripsi. Data yang ditulis ke Kuncichain dilindungi bahkan ketika perangkat terkunci. Kemampuan kunci meliputi:
- [[GALALT:0]]Enkripsi di tempat istirahat menggunakan hardware-backed AES-256.
- [[Eflat-FLT:0]] Akses akses kontrol via passcode perangkat, Touch ID, atau Face ID.
- [[CharlesFLT:0]]Persisten melintasi reinstall aplikasi (jika dikonfigurasi) dan sinkronisasi iCloud opsional.
- [[Objek-oper-FLT:0]]Isolasi[ antara aplikasi: secara default, satu aplikasi tidak dapat membaca item Keychain aplikasi lain kecuali mereka berbagi grup akses Keychain.
Kuncichain tidak dirancang untuk blob besar; menjaga setiap item di bawah beberapa kilobyte. Untuk data yang lebih besar, pertimbangkan menggunakan API atau framework bersama-sama dengan enkripsi berbasis berkas.
API Layanan Keychain untuk Keychain vs Pustaka Ketiga-Bagian
Apple menyediakan native Keychain Services API (berdasarkan C, ), yang kuat tetapi berjela. Anda dapat menggunakannya secara langsung, atau mengadopsi sebuah pelipat Swift-friendly. Pustaka pihak ketiga yang populer seperti KeychainAccess atau SwiftKeychainWrapper[FLT:]]5 kurangi boilerplate. Namun, pemahaman API yang berada di bawah penting untuk debugging dan ketika Anda membutuhkan akses yang baik atas kebijakan. Hari ini kita akan fokus pada API asli.
Storan Kunci Kunci Penyediaan Boin
Keychain sebelum menyimpan apa pun, anda harus memutuskan pada Keychain item class. Yang paling umum untuk kata sandi generik adalah . Untuk kata sandi atau sertifikat Internet, ada kelas lain. Setiap item direferensikan oleh seperangkat atribut ⁇ sebuah kamus (CFDictionary) yang menggambarkan item tersebut.
Aliran dasar selalu mengikuti pola ini:
- Terapkan kamus pertanyaan dengan kelas isian dan atribut.
- BAHASA memanggil fungsi (], , , ).
- Periksa nilai url= (bantuan) ^ atau kode error].
Sebelum menulis kode, impor modul Keamanan:
import Security
import Foundation // for Data and String utilities
Storing Data di Kunci
Mengeluarkan Kata Sandi Generik
Untuk menyimpan token (misalnya, JWT) untuk pengguna saat ini:
func saveToken(_ token: String, forAccount account: String) -> Bool {
guard let tokenData = token.data(using: .utf8) else { return false }
let query: [String: Any] = [
kSecClass as String: kSecClassGenericPassword,
kSecAttrAccount as String: account,
kSecValueData as String: tokenData,
// Optional: restrict access to when device is unlocked
kSecAttrAccessible as String: kSecAttrAccessibleWhenUnlockedThisDeviceOnly
]
// Delete any existing item first to avoid duplicates
SecItemDelete(query as CFDictionary)
let status = SecItemAdd(query as CFDictionary, nil)
return status == errSecSuccess
}
Poin kunci:
- [[Efol:14]] bertindak sebagai kunci primer; pilih string unik (misalnya, ID pengguna atau konstanta seperti ).
- [[OfGAL:16]] kontrol ketika item dapat dibaca. Gunakan untuk keamanan terbaik; mencegah backup iCloud dan membatasi akses ke perangkat saat ini.
- Kami memanggil sebelum menambahkan untuk menghindari akumulasi item duplikat. Sebagai alternatif, Anda dapat menggunakan .
Mengtambahkan Pengendalian Akses (Biometri atau Passcode)
Untuk data yang sangat sensitif, dibutuhkan ID Touch atau ID Wajah sebelum membaca:
let accessControl = SecAccessControlCreateWithFlags(
nil,
kSecAttrAccessibleWhenUnlockedThisDeviceOnly,
.userPresence, // requires passcode, Face ID, or Touch ID
nil
)
let query: [String: Any] = [
kSecClass as String: kSecClassGenericPassword,
kSecAttrAccount as String: account,
kSecValueData as String: tokenData,
kSecAttrAccessControl as String: accessControl as Any
]
SecItemAdd(query as CFDictionary, nil)
Sekarang ini aisaw panggilan untuk item ini akan memicu prompt biometrik atau pascode. Gunakan dari LocalAuthentication untuk menangani interaksi pengguna secara anggun.
¡Ambil Data dari Kunci
Untuk membaca token disimpan:
func retrieveToken(forAccount account: String) -> String? {
let query: [String: Any] = [
kSecClass as String: kSecClassGenericPassword,
kSecAttrAccount as String: account,
kSecReturnData as String: true,
kSecMatchLimit as String: kSecMatchLimitOne
]
var item: CFTypeRef?
let status = SecItemCopyMatching(query as CFDictionary, &item)
guard status == errSecSuccess,
let data = item as? Data,
let token = String(data: data, encoding: .utf8) else {
return nil
}
return token
}
ifford Set to untuk mendapatkan data kembali. Gunakan untuk mengambil hasil tunggal. Jika Anda mengabaikan batas, API mungkin akan mengembalikan sebuah array.
[5] elash Important: Ketika menggunakan kontrol akses (biometri), panggilan mungkin akan kembali jika pengguna membatalkan. Menangani kasus ini secara terpisah dan tidak pernah jatuh kembali ke penyimpanan teks biasa.
Mengemaskini dan Menghapuskan Kuncichain Item
Mengemaskinikan Item yang Telah Ada
Ketimbang menghapus dan menambahkan kembali, gunakan :
func updateToken(_ newToken: String, forAccount account: String) -> Bool {
guard let newData = newToken.data(using: .utf8) else { return false }
let query: [String: Any] = [
kSecClass as String: kSecClassGenericPassword,
kSecAttrAccount as String: account
]
let attributesToUpdate: [String: Any] = [
kSecValueData as String: newData
]
let status = SecItemUpdate(query as CFDictionary, attributesToUpdate as CFDictionary)
return status == errSecSuccess
}
Ini lebih efisien daripada steck+add, dan menghindari kondisi ras potensial.
Memadam item
func deleteItem(forAccount account: String) -> Bool {
let query: [String: Any] = [
kSecClass as String: kSecClassGenericPassword,
kSecAttrAccount as String: account
]
let status = SecItemDelete(query as CFDictionary)
return status == errSecSuccess
}
Berhati-hatilah untuk tidak menghapus item yang termasuk ke dalam aplikasi lain berbagi kelompok akses yang sama ⁇ selalu skop pertanyaan Anda dengan jika Anda menggunakan Keychains berbagi.
Kebolehcapaian dan Kebolehcapaian Kebolehcapaian
Parameter konstanta mendefinisikan bila Butir Keychain dapat dibaca. Pilih pilihan paling membatasi yang masih memenuhi kebutuhan aplikasi Anda:
| Attribute | Meaning |
|---|---|
kSecAttrAccessibleWhenUnlocked | Available only while device is unlocked (default). |
kSecAttrAccessibleAfterFirstUnlock | Available after device boots and is unlocked once. Allows background access. |
kSecAttrAccessibleWhenPasscodeSetThisDeviceOnly | Requires a passcode to be set. Strictest option—prevents access even after unlock if passcode is removed. |
kSecAttrAccessibleWhenUnlockedThisDeviceOnly | Same as WhenUnlocked but does not back up to iCloud, and cannot be restored to another device. |
Untuk kebanyakan aplikasi, menyerang keseimbangan yang tepat antara keamanan dan kemampuan kita. Jika Anda perlu membaca item di latar belakang (misalnya, sebuah token refresh latar belakang), Anda harus menggunakan (dan menerima bahwa data sedikit kurang dilindungi).
Kesalahan Penanganan dan Air Terjun Umum
BAHASA fungsi mengembalikan . Selalu periksa dan tangani kegagalan dengan sesuai. Galat umum:
- ( ⁇ 300) ⁇ Tidak ada item yang cocok dengan pertanyaan.
- ( ⁇ 299) ⁇ Sebuah item dengan kunci primer yang sama sudah ada (jika Anda tidak menghapus terlebih dahulu).
- ( ⁇ 8] ⁇ Promp biometrik dibatalkan pengguna.
- [[CharleFLT:46]] ( ⁇ 293) ⁇ Otentikasi gagal atau biometrik tidak tersedia.
Tak pernah mengabaikan status non-sukses. Dengan senang hati merendahkan: menunjukkan pesan kesalahan atau coba lagi, tetapi jangan pernah menyimpan data sensitif di luar Keychain sebagai fallback. Anda dapat menggunakan untuk memeriksa ketersediaan biometrik sebelum mencoba mengakses.
Praktek dan Pertimbangan Produksi Terbaik Praktek dan Praktik Terbaik
- [[LRT:0]]Gunakan nama akun yang unik dan deskriptif per pengguna atau per jenis item untuk menghindari tabrakan.
- [[EfLANFLT:0]]Always menyatakan atribut aksesibilitas; sebaliknya, default sistem (]) diterapkan, yang mungkin tidak ideal.
- [[LORNFLT:0]]Clear Data Keychain ketika pengguna log keluar ⁇ mengiterati seluruh akun dan hapus item yang diketahui.
- Gunakan Keychain Access Groups hanya ketika berbagi antara aplikasi Anda sendiri. Hindari kelompok luas.
- [[OGNOFLT:0]]Jangan simpan data tidak sensitif (seperti preferensi pengguna) di Keychain ⁇ guna atau database sebagai gantinya.
- [[Eflat:0]]Consider menggunakan dengan untuk skenario lanjutan (macOS Catalyst).
- [[Ujilah[ZOZANFLT:0]]Uji pada perangkat nyata; Simulator menggunakan Keychain perangkat lunak yang berperilaku berbeda dari penyimpanan yang didukung perangkat keras.
Woinza Menggunakan Keychain dengan SwiftUI dan Async/Await
Untuk aplikasi modern, balut operasi Keychain dalam aktor atau kelas aman-sync untuk menghindari pemblokiran benang utama. Contoh menggunakan :
actor KeychainManager {
func saveToken(_ token: String, for account: String) async -> Bool {
// same implementation as above, but now it's safe to call from any context
return saveToken(token, forAccount: account)
}
}
Keanfanfien Jika Anda menggunakan biometrik, panggilan mungkin akan memblokir benang sambil menunggu interaksi pengguna. Lipat di antrian latar belakang, atau lebih baik, gunakan ] metode sebelum panggilan Keychain.
Kekecualian Kesimpulan
The iOS Keychain is the correct place to store small, sensitive pieces of data. By using the native Keychain Services API, you gain direct control over encryption, accessibility, and authentication policies. Always pair your Keychain usage with solid error handling and remember to clear data when appropriate. For further reading, refer to the Apple Keychain Service Documentation and the Keychain Concepts overview. Adopting these practices will help you ship iOS apps that respect user privacy and withstand security scrutiny.