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).


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];

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


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.


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 .


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!


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];

3

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


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.


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"];

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.


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?).


1

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



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];
Dengan menggunakan situs kami, Anda mengakui telah membaca dan memahami Kebijakan Cookie dan Kebijakan Privasi kami.
Licensed under cc by-sa 3.0 with attribution required.