iOS: Bagaimana cara menyimpan nama pengguna / kata sandi dalam suatu aplikasi?

276

Saya memiliki layar masuk di aplikasi iOS saya. Nama pengguna dan kata sandi akan disimpan dalam NSUserDefaultsdan dimuat ke layar login lagi ketika Anda memasukkan aplikasi lagi (tentu saja, NSUserDefaultspermanen).

Sekarang, pengguna memiliki kemungkinan untuk menonaktifkan fitur penyimpanan nama pengguna / kata sandi.

Jadi NSUserDefaultsakan dibersihkan kemudian.

Tetapi dalam aplikasi saya, saya memerlukan nama pengguna / kata sandi ini untuk permintaan basis data bagi pengguna. Jadi: Di ​​mana menyimpan data kecuali NSUserDefaults? (Tempat ini dapat / harus dihapus ketika pengguna keluar dari aplikasi atau logout).

Kovu
sumber
Pengguna hanya dapat menghapusnya dengan mengatur ulang perangkat atau menghapus aplikasi. Apakah saya melewatkan sesuatu?
3
Dan omong-omong, jika data harus dihapus ketika pengguna berhenti dari aplikasi, mengapa tidak menyimpannya di RAM?
10
Anda harus serius mempertimbangkan untuk menggunakan Gantungan Kunci untuk menyimpan nama pengguna dan kata sandi alih-alih NSUserDefaults.
Filip Radelic
1
Anda bisa mendapatkan ide dasar tentang implementasi swift3 dari sini
Anish Parajuli 웃
Tolong haruskah saya selalu menggunakan kSecValueData dan kSecValueData sebagai kunci? Atau bisakah saya menggunakan string apa pun sebagai kunci?
Ne AS

Jawaban:

424

Anda harus selalu menggunakan Keychain untuk menyimpan nama pengguna dan kata sandi, dan karena itu disimpan dengan aman dan hanya dapat diakses ke aplikasi Anda, tidak perlu menghapusnya ketika aplikasi berhenti (jika itu menjadi perhatian Anda).

Apple memberikan kode sampel yang menyimpan, membaca, dan menghapus item gantungan kunci dan di sini adalah cara menggunakan kelas pembungkus gantungan kunci dari sampel yang sangat disederhanakan menggunakan Keychain.

Sertakan Security.framework (di Xcode 3 klik kanan pada folder frameworks dan tambahkan framework yang ada. Di Xcode 4 pilih proyek Anda, lalu pilih target, pergi ke tab Bangun Fase dan klik + di bawah Tautan Biner Dengan File) dan KeychainItemWrapper .h &. m file ke proyek Anda, # impor file .h di mana pun Anda perlu menggunakan gantungan kunci dan kemudian buat instance dari kelas ini:

KeychainItemWrapper *keychainItem = [[KeychainItemWrapper alloc] initWithIdentifier:@"YourAppLogin" accessGroup:nil];

( YourAppLogin dapat berupa apa saja yang Anda pilih untuk memanggil item Keychain Anda dan Anda dapat memiliki banyak item jika diperlukan)

Kemudian Anda dapat mengatur nama pengguna dan kata sandi menggunakan:

[keychainItem setObject:@"password you are saving" forKey:kSecValueData];
[keychainItem setObject:@"username you are saving" forKey:kSecAttrAccount];

Dapatkan mereka menggunakan:

NSString *password = [keychainItem objectForKey:kSecValueData];
NSString *username = [keychainItem objectForKey:kSecAttrAccount];

Atau hapus menggunakan:

[keychainItem resetKeychainItem];
Filip Radelic
sumber
5
Saya telah memperbarui jawaban saya dengan kode dan deskripsi. Ini tidak sesulit yang Anda kira.
Filip Radelic
44
PERHATIAN! Silakan tambahkan jawaban Anda, bahwa hanya "salin KeychainItemWrapper" tidak cukup! Saya punya masalah, bahwa saya tidak bisa membangunnya setelah itu! Anda harus menambahkan security.framework ke proyek Anda bahwa KeychainItemWrapper akan bekerja! (HowTo: Select Project -> Select Target -> Pilih Tab "Build Phases" -> Pilih "Tautan Biner Dengan Libaries" -> "+" -> tambah Security.Framework)
Kovu
63
Saat menggunakan ARC, kompiler akan berteriak kepada Anda untuk menggunakan konstanta kSecValueDatadan kSecAttrAccountdalam kode Objective-C, jadi pastikan untuk melemparkannya menggunakan (__bridge id), misalnya, [keychainItem setObject:obj forKey:(__bridge id)kSecValueData];
Joe Hankin
7
KeychainItemWrapper.m tampaknya memiliki kebocoran memori pada baris 196. Mengubah baris ke "self.keychainItemData = [[[NSMutableDictionary dialokasikan] init] autorelease];" memperbaikinya.
Olof
12
Saat menggunakan ARC, kode yang diperbarui telah diberikan di sini oleh Apple. Lihatlah Listing 2-1. Meski pendekatannya sama.
Rick
97

Jika Anda memerlukan versi ARC dari pembungkus di sini adalah tautan https://gist.github.com/1170641 Terima kasih kepada

Manuel Pintaldi
sumber
Terima kasih, saya mendapatkan KeychainItemWrapper .h & .m dari URL itu.
Parthpatel1105
48

Solusi yang sangat mudah melalui Gantungan Kunci .

Ini adalah pembungkus sederhana untuk sistem Keychain. Cukup tambahkan SSKeychain.h, SSKeychain.m, SSKeychainQuery.hdan SSKeychainQuery.mfile untuk proyek Anda dan menambahkan Security.framework untuk target Anda.

Untuk menyimpan kata sandi:

[SSKeychain setPassword:@"AnyPassword" forService:@"AnyService" account:@"AnyUser"]

Untuk mengambil kata sandi:

NSString *password = [SSKeychain passwordForService:@"AnyService" account:@"AnyUser"];

Di mana setPasswordnilai yang ingin Anda simpan dan forServicevariabel apa yang Anda inginkan disimpan dan akun untuk pengguna / objek mana kata sandi dan info lainnya untuk.

berkelanjutan86
sumber
Apakah Anda tahu cara menggunakan sskeychain untuk menyinkronkan aplikasi dengan nama pengguna dan kata sandi yang sama?
Joe Shamuraq
4
bagaimana Anda menyimpan nama pengguna di samping kata sandi? Bagaimana Anda menghapus seluruh akun dari SSKeychain? Keduanya tidak disebutkan dokumen
user798719
2
Untuk mendapatkan nama pengguna, lakukan NSString *username = [[SSKeychain accountsForService:@"AnyService"][0] valueForKey:@"acct"]. Ini akan berfungsi dengan baik jika Anda hanya menggunakan satu akun. Seperti biasa, pastikan untuk memeriksa panjang array sebelum mencoba mengakses indeks 0.
Harga Jared
27

Anda cukup menggunakan NSURLCredential, itu akan menyimpan nama pengguna dan kata sandi di gantungan kunci hanya dalam dua baris kode .

Lihat jawaban terinci saya .

Phil
sumber
13

Saya memutuskan untuk menjawab bagaimana menggunakan gantungan kunci di iOS 8 menggunakan Obj-C dan ARC.

1) Saya menggunakan keychainItemWrapper (versi ARCifief) dari GIST: https://gist.github.com/dhoerl/1170641/download - Tambahkan (+ salin) KeychainItemWrapper.h dan .m ke proyek Anda

2) Tambahkan kerangka Keamanan ke proyek Anda (periksa proyek> Bangun fase> Tautkan biner dengan Perpustakaan)

3) Tambahkan perpustakaan keamanan (#import) dan KeychainItemWrapper (#import "KeychainItemWrapper.h") ke file .h dan .m di mana Anda ingin menggunakan gantungan kunci.

4) Untuk menyimpan data ke gantungan kunci:

NSString *emailAddress = self.txtEmail.text;
NSString *password = self.txtPasword.text;
//because keychain saves password as NSData object
NSData *pwdData = [password dataUsingEncoding:NSUTF8StringEncoding];

//Save item
self.keychainItem = [[KeychainItemWrapper alloc] initWithIdentifier:@"YourAppLogin" accessGroup:nil];
[self.keychainItem setObject:emailAddress forKey:(__bridge id)(kSecAttrAccount)];
[self.keychainItem setObject:pwdData forKey:(__bridge id)(kSecValueData)];

5) Baca data (mungkin layar login saat memuat> viewDidLoad):

self.keychainItem = [[KeychainItemWrapper alloc] initWithIdentifier:@"YourAppLogin" accessGroup:nil];

self.txtEmail.text = [self.keychainItem objectForKey:(__bridge id)(kSecAttrAccount)];

//because label uses NSString and password is NSData object, conversion necessary
NSData *pwdData = [self.keychainItem objectForKey:(__bridge id)(kSecValueData)];
NSString *password = [[NSString alloc] initWithData:pwdData encoding:NSUTF8StringEncoding];
self.txtPassword.text = password;

Nikmati!

D_RBD
sumber
11

Jika Anda mengalami masalah saat mengambil kata sandi menggunakan pembungkus gantungan kunci, gunakan kode ini:

NSData *pass =[keychain objectForKey:(__bridge id)(kSecValueData)];
NSString *passworddecoded = [[NSString alloc] initWithData:pass
                                           encoding:NSUTF8StringEncoding];
Robby891
sumber
3

checkout kode sampel ini saya mencoba dulu pembungkus apel dari kode sampel tetapi ini jauh lebih mudah bagi saya

BSevo
sumber
2

coba yang ini:

 KeychainItemWrapper *keychainItem = [[KeychainItemWrapper alloc] initWithIdentifier:@"YourAppLogin" accessGroup:nil];
[keychainItem setObject:@"password you are saving" forKey:kSecValueData]; 
[keychainItem setObject:@"username you are saving" forKey:kSecAttrAccount];

semoga akan membantu.

Vara
sumber
2

Saya melihat menggunakan KeychainItemWrapper (versi ARC) tapi saya tidak menemukan pembungkus Objective C-nya sehat seperti yang diinginkan.

Saya menggunakan solusi ini oleh Kishikawa Katsumi , yang berarti saya menulis lebih sedikit kode dan tidak harus menggunakan gips untuk menyimpan nilai NSString.

Dua contoh penyimpanan:

[UICKeyChainStore setString:@"kishikawakatsumi" forKey:@"username"];
[UICKeyChainStore setString:@"P455_w0rd$1$G$Z$" forKey:@"password"];

Dua contoh pengambilan

UICKeyChainStore *store = [UICKeyChainStore keyChainStore];
    // or
UICKeyChainStore *store = [UICKeyChainStore keyChainStoreWithService:@"YOUR_SERVICE"];

NSString *username = [store stringForKey:@"username"];
NSString *password = [store stringForKey:@"password"];
Carl
sumber
2

Ada bug kecil dalam kode di atas (omong-omong Dave itu sangat membantu posting Anda, terima kasih)

Di bagian tempat kami menyimpan kredensial, kode tersebut juga memerlukan kode berikut agar berfungsi dengan benar.

[self.keychainItem setObject:@"myCredentials" forKey:(__bridge id)(kSecAttrService)];

paling mungkin adalah karena kedua kalinya kami mencoba (kembali) masuk dengan kredensial yang sama dengan yang ditemukan di item gantungan kunci dan aplikasi mogok. dengan kode di atas berfungsi seperti pesona.

Realitas
sumber
2

Untuk memperbarui pertanyaan ini:

Bagi mereka yang menggunakan Swift checkout, penerapan drag and drop swift ini oleh Mihai Costea mendukung grup akses:

https://github.com/macostea/KeychainItemWrapper.swift/blob/master/KeychainItemWrapper.swift

Sebelum menggunakan gantungan kunci: pertimbangkan dua kali sebelum menyimpan kata sandi. Dalam banyak kasus menyimpan token otentikasi (seperti id sesi persistensi) dan email atau nama akun mungkin cukup. Anda dapat dengan mudah membatalkan token otentikasi untuk memblokir akses yang tidak sah, mengharuskan pengguna untuk login lagi pada perangkat yang dikompromikan tetapi tidak memerlukan reset kata sandi dan harus login lagi pada semua perangkat (kita tidak hanya menggunakan Apple, kan?).

pizzamonster
sumber
1

Tapi, sekarang Anda bisa menggunakan NURLCredential sebagai ganti bungkus gantungan kunci. Itu melakukan apa yang perlu kita lakukan.

Sumitiscreative
sumber
0

Berikut ini akan berfungsi dengan baik:

KeychainItemWrapper *keychainItem = [[KeychainItemWrapper alloc] initWithIdentifier:@"YourAppLogin" accessGroup:nil];
[keychainItem setObject:@"password you are saving" forKey:kSecValueData]; 
[keychainItem setObject:@"username you are saving" forKey:kSecAttrAccount];
pkamb
sumber