iOS 使用Keychain 保存 用户名和密码到 本地
iOS 使用Keychain 保存 用户名和密码到 本地
之前曾把一些简单的数据保存在了plist,文件,及NsuserDefault里面,
但是如果要保存密码之类的,保存在本地就很不安全了;
但是利用 Keychain 我们可以很安全的把 用户密码等信息保存在本地
1:使用苹果官方封装好的Keychain操作类
2:使用 开源的keychain操作
![](https://images.cnblogs.com/OutliningIndicators/ContractedBlock.gif)
#import <XCTest/XCTest.h> #import "SSKeychain.h" static NSString *const kSSKeychainServiceName = @"SSToolkitTestService"; static NSString *const kSSKeychainAccountName = @"SSToolkitTestAccount"; static NSString *const kSSKeychainPassword = @"SSToolkitTestPassword"; static NSString *const kSSKeychainLabel = @"SSToolkitLabel"; @interface SSKeychainTests : XCTestCase @end @implementation SSKeychainTests - (void)testNewItem { // New item SSKeychainQuery *query = [[SSKeychainQuery alloc] init]; query.password = kSSKeychainPassword; query.service = kSSKeychainServiceName; query.account = kSSKeychainAccountName; query.label = kSSKeychainLabel; NSError *error; XCTAssertTrue([query save:&error], @"Unable to save item: %@", error); // Look up query = [[SSKeychainQuery alloc] init]; query.service = kSSKeychainServiceName; query.account = kSSKeychainAccountName; query.password = nil; XCTAssertTrue([query fetch:&error], @"Unable to fetch keychain item: %@", error); XCTAssertEqualObjects(query.password, kSSKeychainPassword, @"Passwords were not equal"); // Search for all accounts query = [[SSKeychainQuery alloc] init]; NSArray *accounts = [query fetchAll:&error]; XCTAssertNotNil(accounts, @"Unable to fetch accounts: %@", error); XCTAssertTrue([self _accounts:accounts containsAccountWithName:kSSKeychainAccountName], @"Matching account was not returned"); // Check accounts for service query.service = kSSKeychainServiceName; accounts = [query fetchAll:&error]; XCTAssertNotNil(accounts, @"Unable to fetch accounts: %@", error); XCTAssertTrue([self _accounts:accounts containsAccountWithName:kSSKeychainAccountName], @"Matching account was not returned"); // Delete query = [[SSKeychainQuery alloc] init]; query.service = kSSKeychainServiceName; query.account = kSSKeychainAccountName; XCTAssertTrue([query deleteItem:&error], @"Unable to delete password: %@", error); } - (void)testPasswordObject { SSKeychainQuery *query = [[SSKeychainQuery alloc] init]; query.service = kSSKeychainServiceName; query.account = kSSKeychainAccountName; NSDictionary *dictionary = @{@"number": @42, @"string": @"Hello World"}; query.passwordObject = dictionary; NSError *error; XCTAssertTrue([query save:&error], @"Unable to save item: %@", error); query = [[SSKeychainQuery alloc] init]; query.service = kSSKeychainServiceName; query.account = kSSKeychainAccountName; query.passwordObject = nil; XCTAssertTrue([query fetch:&error], @"Unable to fetch keychain item: %@", error); XCTAssertEqualObjects(query.passwordObject, dictionary, @"Passwords were not equal"); } - (void)testMissingInformation { SSKeychainQuery *query = [[SSKeychainQuery alloc] init]; query.service = kSSKeychainServiceName; query.account = kSSKeychainAccountName; NSError *error; XCTAssertFalse([query save:&error], @"Function should return NO as not all needed information is provided: %@", error); query = [[SSKeychainQuery alloc] init]; query.password = kSSKeychainPassword; query.account = kSSKeychainAccountName; XCTAssertFalse([query save:&error], @"Function should return NO as not all needed information is provided: %@", error); query = [[SSKeychainQuery alloc] init]; query.password = kSSKeychainPassword; query.service = kSSKeychainServiceName; XCTAssertFalse([query save:&error], @"Function save should return NO if not all needed information is provided: %@", error); } - (void)testDeleteWithMissingInformation { SSKeychainQuery *query = [[SSKeychainQuery alloc] init]; query.account = kSSKeychainAccountName; NSError *error; XCTAssertFalse([query deleteItem:&error], @"Function deleteItem should return NO if not all needed information is provided: %@", error); query = [[SSKeychainQuery alloc] init]; query.service = kSSKeychainServiceName; XCTAssertFalse([query deleteItem:&error], @"Function deleteItem should return NO if not all needed information is provided: %@", error); // check if fetch handels missing information correctly query = [[SSKeychainQuery alloc] init]; query.account = kSSKeychainAccountName; XCTAssertFalse([query fetch:&error], @"Function fetch should return NO if not all needed information is provided: %@", error); query = [[SSKeychainQuery alloc] init]; query.service = kSSKeychainServiceName; XCTAssertFalse([query fetch:&error], @"Function fetch should return NO if not all needed information is provided: %@", error); query = [[SSKeychainQuery alloc] init]; query.service = kSSKeychainServiceName; XCTAssertFalse([query fetch:NULL], @"Function fetch should return NO if not all needed information is provided and error is NULL"); } - (void)testSynchronizable { SSKeychainQuery *query = [[SSKeychainQuery alloc] init]; query.service = kSSKeychainServiceName; query.account = kSSKeychainAccountName; query.password = kSSKeychainPassword; query.synchronizationMode = SSKeychainQuerySynchronizationModeYes; NSError *error; XCTAssertTrue([query save:&error], @"Unable to save item: %@", error); query = [[SSKeychainQuery alloc] init]; query.service = kSSKeychainServiceName; query.account = kSSKeychainAccountName; query.password = nil; query.synchronizationMode = SSKeychainQuerySynchronizationModeNo; XCTAssertFalse([query fetch:&error], @"Fetch should fail when trying to fetch an unsynced password that was saved as synced: %@", error); XCTAssertFalse([query fetch:NULL], @"Fetch should fail when trying to fetch an unsynced password that was saved as synced. error == NULL"); XCTAssertNotEqualObjects(query.password, kSSKeychainPassword, @"Passwords should not be equal when trying to fetch an unsynced password that was saved as synced."); query = [[SSKeychainQuery alloc] init]; query.service = kSSKeychainServiceName; query.account = kSSKeychainAccountName; query.password = nil; query.synchronizationMode = SSKeychainQuerySynchronizationModeAny; XCTAssertTrue([query fetch:&error], @"Unable to fetch keychain item: %@", error); XCTAssertEqualObjects(query.password, kSSKeychainPassword, @"Passwords were not equal"); } // Test Class Methods of SSKeychain - (void)testSSKeychain { NSError *error = nil; // create a new keychain item XCTAssertTrue([SSKeychain setPassword:kSSKeychainPassword forService:kSSKeychainServiceName account:kSSKeychainAccountName error:&error], @"Unable to save item: %@", error); // check password XCTAssertEqualObjects([SSKeychain passwordForService:kSSKeychainServiceName account:kSSKeychainAccountName], kSSKeychainPassword, @"Passwords were not equal"); // check all accounts XCTAssertTrue([self _accounts:[SSKeychain allAccounts] containsAccountWithName:kSSKeychainAccountName], @"Matching account was not returned"); // check account XCTAssertTrue([self _accounts:[SSKeychain accountsForService:kSSKeychainServiceName] containsAccountWithName:kSSKeychainAccountName], @"Matching account was not returned"); // delete password XCTAssertTrue([SSKeychain deletePasswordForService:kSSKeychainServiceName account:kSSKeychainAccountName error:&error], @"Unable to delete password: %@", error); // set password and delete it without error function XCTAssertTrue([SSKeychain setPassword:kSSKeychainPassword forService:kSSKeychainServiceName account:kSSKeychainAccountName], @"Unable to save item"); XCTAssertTrue([SSKeychain deletePasswordForService:kSSKeychainServiceName account:kSSKeychainAccountName], @"Unable to delete password"); #if __IPHONE_4_0 && TARGET_OS_IPHONE [SSKeychain setAccessibilityType:kSecAttrAccessibleWhenUnlockedThisDeviceOnly]; XCTAssertTrue([SSKeychain accessibilityType] == kSecAttrAccessibleWhenUnlockedThisDeviceOnly, @"Unable to verify accessibilityType"); #endif } #pragma mark - Private - (BOOL)_accounts:(NSArray *)accounts containsAccountWithName:(NSString *)name { for (NSDictionary *dictionary in accounts) { if ([[dictionary objectForKey:@"acct"] isEqualToString:name]) { return YES; } } return NO; } @end
![](https://images.cnblogs.com/OutliningIndicators/ContractedBlock.gif)
#import <XCTest/XCTest.h> #import "UICKeyChainStore.h" @interface UICKeyChainStoreTests : XCTestCase { NSString *kStubKey; NSString *kStubString; NSString *kStubService; } @end @implementation UICKeyChainStoreTests - (void)setUp { [super setUp]; kStubKey = @"password"; kStubString = @"password1234"; kStubService = @"com.kishikawakatsumi"; [UICKeyChainStore setDefaultService:kStubService]; [UICKeyChainStore removeAllItems]; } - (void)tearDown { [super tearDown]; } - (void)testSetDefaultService { NSString *serviceName = @"com.kishikawakatsumi.UICKeyChainStore"; [UICKeyChainStore setDefaultService:serviceName]; XCTAssertEqualObjects(serviceName, [UICKeyChainStore defaultService], @"specitfy default service name"); } - (void)testInitializers { UICKeyChainStore *store = nil; store = [UICKeyChainStore keyChainStore]; XCTAssertEqualObjects(store.service, [UICKeyChainStore defaultService], @"instantiate default store"); store = [[UICKeyChainStore alloc] init]; XCTAssertEqualObjects(store.service, [UICKeyChainStore defaultService], @"instantiate default store"); NSString *serviceName = @"com.kishikawakatsumi.UICKeyChainStore"; store = [UICKeyChainStore keyChainStoreWithService:serviceName]; XCTAssertEqualObjects(store.service, serviceName, @"instantiate custom service named store"); } - (void)testSetData { NSString *usernameKey = @"username"; NSString *passwordKey = @"password"; NSString *username = @"kishikawakatsumi"; NSString *password = @"password1234"; NSData *usernameData = [username dataUsingEncoding:NSUTF8StringEncoding]; NSData *passwordData = [password dataUsingEncoding:NSUTF8StringEncoding]; [UICKeyChainStore setData:[username dataUsingEncoding:NSUTF8StringEncoding] forKey:usernameKey]; [UICKeyChainStore setData:[password dataUsingEncoding:NSUTF8StringEncoding] forKey:passwordKey]; XCTAssertEqualObjects([UICKeyChainStore dataForKey:usernameKey], usernameData, @"stored username"); XCTAssertEqualObjects([UICKeyChainStore dataForKey:passwordKey], passwordData, @"stored password"); [UICKeyChainStore removeItemForKey:usernameKey service:[UICKeyChainStore defaultService]]; XCTAssertNil([UICKeyChainStore dataForKey:usernameKey], @"removed username"); XCTAssertEqualObjects([UICKeyChainStore dataForKey:passwordKey], passwordData, @"left password"); [UICKeyChainStore removeItemForKey:passwordKey service:[UICKeyChainStore defaultService]]; XCTAssertNil([UICKeyChainStore dataForKey:usernameKey], @"removed username"); XCTAssertNil([UICKeyChainStore dataForKey:passwordKey], @"removed password"); } - (void)testSetDataWithNoError { NSString *usernameKey = @"username"; NSString *passwordKey = @"password"; NSString *username = @"kishikawakatsumi"; NSString *password = @"password1234"; NSData *usernameData = [username dataUsingEncoding:NSUTF8StringEncoding]; NSData *passwordData = [password dataUsingEncoding:NSUTF8StringEncoding]; NSError *error; [UICKeyChainStore setData:[username dataUsingEncoding:NSUTF8StringEncoding] forKey:usernameKey error:&error]; XCTAssertNil(error, @"no error"); XCTAssertEqualObjects([UICKeyChainStore dataForKey:usernameKey error:&error], usernameData, @"stored username"); XCTAssertNil(error, @"no error"); [UICKeyChainStore setData:[password dataUsingEncoding:NSUTF8StringEncoding] forKey:passwordKey error:&error]; XCTAssertNil(error, @"no error"); XCTAssertEqualObjects([UICKeyChainStore dataForKey:passwordKey error:&error], passwordData, @"stored password"); XCTAssertNil(error, @"no error"); [UICKeyChainStore removeItemForKey:usernameKey service:[UICKeyChainStore defaultService] error:&error]; XCTAssertNil(error, @"no error"); XCTAssertNil([UICKeyChainStore dataForKey:usernameKey error:&error], @"removed username"); XCTAssertNil(error, @"no error"); XCTAssertEqualObjects([UICKeyChainStore dataForKey:passwordKey error:&error], passwordData, @"left password"); XCTAssertNil(error, @"no error"); [UICKeyChainStore removeItemForKey:passwordKey service:[UICKeyChainStore defaultService] error:&error]; XCTAssertNil(error, @"no error"); XCTAssertNil([UICKeyChainStore dataForKey:usernameKey error:&error], @"removed username"); XCTAssertNil(error, @"no error"); XCTAssertNil([UICKeyChainStore dataForKey:passwordKey error:&error], @"removed password"); XCTAssertNil(error, @"no error"); } - (void)testSetNilData { NSString *usernameKey = @"username"; NSString *passwordKey = @"password"; NSString *username = @"kishikawakatsumi"; NSString *password = @"password1234"; NSData *usernameData = [username dataUsingEncoding:NSUTF8StringEncoding]; NSData *passwordData = [password dataUsingEncoding:NSUTF8StringEncoding]; [UICKeyChainStore setData:nil forKey:usernameKey]; [UICKeyChainStore setData:nil forKey:passwordKey]; XCTAssertNil([UICKeyChainStore dataForKey:usernameKey], @"no username"); XCTAssertNil([UICKeyChainStore dataForKey:passwordKey], @"no password"); [UICKeyChainStore setData:[username dataUsingEncoding:NSUTF8StringEncoding] forKey:usernameKey]; [UICKeyChainStore setData:[password dataUsingEncoding:NSUTF8StringEncoding] forKey:passwordKey]; XCTAssertEqualObjects([UICKeyChainStore dataForKey:usernameKey], usernameData, @"stored username"); XCTAssertEqualObjects([UICKeyChainStore dataForKey:passwordKey], passwordData, @"stored password"); [UICKeyChainStore setData:nil forKey:usernameKey]; XCTAssertNil([UICKeyChainStore dataForKey:usernameKey], @"removed username"); XCTAssertEqualObjects([UICKeyChainStore dataForKey:passwordKey], passwordData, @"left password"); [UICKeyChainStore setData:nil forKey:passwordKey]; XCTAssertNil([UICKeyChainStore dataForKey:usernameKey], @"removed username"); XCTAssertNil([UICKeyChainStore dataForKey:passwordKey], @"removed password"); [UICKeyChainStore removeItemForKey:usernameKey]; XCTAssertNil([UICKeyChainStore dataForKey:usernameKey], @"removed username"); XCTAssertNil([UICKeyChainStore dataForKey:passwordKey], @"removed password"); [UICKeyChainStore removeItemForKey:passwordKey]; XCTAssertNil([UICKeyChainStore dataForKey:usernameKey], @"removed username"); XCTAssertNil([UICKeyChainStore dataForKey:passwordKey], @"removed password"); } - (void)testSetUsernameAndPassword { NSString *usernameKey = @"username"; NSString *passwordKey = @"password"; NSString *username = @"kishikawakatsumi"; NSString *password = @"password1234"; UICKeyChainStore *store = [UICKeyChainStore keyChainStore]; [store removeAllItems]; [UICKeyChainStore setString:username forKey:usernameKey]; [UICKeyChainStore setString:password forKey:passwordKey]; XCTAssertEqualObjects([UICKeyChainStore stringForKey:usernameKey], username, @"stored username"); XCTAssertEqualObjects([UICKeyChainStore stringForKey:passwordKey], password, @"stored password"); XCTAssertEqualObjects([store stringForKey:usernameKey], username, @"stored username"); XCTAssertEqualObjects([store stringForKey:passwordKey], password, @"stored password"); [UICKeyChainStore removeItemForKey:usernameKey]; XCTAssertNil([UICKeyChainStore stringForKey:usernameKey], @"removed username"); XCTAssertEqualObjects([UICKeyChainStore stringForKey:passwordKey], password, @"left password"); XCTAssertEqualObjects([store stringForKey:passwordKey], password, @"left password"); [UICKeyChainStore removeItemForKey:passwordKey]; XCTAssertNil([UICKeyChainStore stringForKey:usernameKey], @"removed username"); XCTAssertNil([UICKeyChainStore stringForKey:passwordKey], @"removed password"); XCTAssertNil([store stringForKey:usernameKey], @"removed username"); XCTAssertNil([store stringForKey:passwordKey], @"removed password"); } - (void)testSetUsernameAndPasswordWithNoError { NSString *usernameKey = @"username"; NSString *passwordKey = @"password"; NSString *username = @"kishikawakatsumi"; NSString *password = @"password1234"; NSError *error; UICKeyChainStore *store = [UICKeyChainStore keyChainStore]; [store removeAllItemsWithError:&error]; XCTAssertNil(error, @"no error"); [UICKeyChainStore setString:username forKey:usernameKey error:&error]; XCTAssertNil(error, @"no error"); [UICKeyChainStore setString:password forKey:passwordKey error:&error]; XCTAssertNil(error, @"no error"); XCTAssertEqualObjects([UICKeyChainStore stringForKey:usernameKey error:&error], username, @"stored username"); XCTAssertNil(error, @"no error"); XCTAssertEqualObjects([UICKeyChainStore stringForKey:passwordKey error:&error], password, @"stored password"); XCTAssertNil(error, @"no error"); XCTAssertEqualObjects([store stringForKey:usernameKey error:&error], username, @"stored username"); XCTAssertNil(error, @"no error"); XCTAssertEqualObjects([store stringForKey:passwordKey error:&error], password, @"stored password"); XCTAssertNil(error, @"no error"); [UICKeyChainStore removeItemForKey:usernameKey error:&error]; XCTAssertNil(error, @"no error"); XCTAssertNil([UICKeyChainStore stringForKey:usernameKey error:&error], @"removed username"); XCTAssertNil(error, @"no error"); XCTAssertEqualObjects([UICKeyChainStore stringForKey:passwordKey error:&error], password, @"left password"); XCTAssertNil(error, @"no error"); XCTAssertEqualObjects([store stringForKey:passwordKey error:&error], password, @"left password"); XCTAssertNil(error, @"no error"); [UICKeyChainStore removeItemForKey:passwordKey error:&error]; XCTAssertNil(error, @"no error"); XCTAssertNil([UICKeyChainStore stringForKey:usernameKey error:&error], @"removed username"); XCTAssertNil(error, @"no error"); XCTAssertNil([UICKeyChainStore stringForKey:passwordKey error:&error], @"removed password"); XCTAssertNil(error, @"no error"); XCTAssertNil([store stringForKey:usernameKey error:&error], @"removed username"); XCTAssertNil(error, @"no error"); XCTAssertNil([store stringForKey:passwordKey error:&error], @"removed password"); XCTAssertNil(error, @"no error"); } - (void)testSetNilUsernameAndNilPassword { NSString *usernameKey = @"username"; NSString *passwordKey = @"password"; NSString *username = @"kishikawakatsumi"; NSString *password = @"password1234"; UICKeyChainStore *store = [UICKeyChainStore keyChainStore]; [store removeAllItems]; [UICKeyChainStore setString:nil forKey:usernameKey]; [UICKeyChainStore setString:nil forKey:passwordKey]; XCTAssertNil([UICKeyChainStore dataForKey:usernameKey], @"no username"); XCTAssertNil([UICKeyChainStore dataForKey:passwordKey], @"no password"); [UICKeyChainStore setString:username forKey:usernameKey]; [UICKeyChainStore setString:password forKey:passwordKey]; XCTAssertEqualObjects([UICKeyChainStore stringForKey:usernameKey], username, @"stored username"); XCTAssertEqualObjects([UICKeyChainStore stringForKey:passwordKey], password, @"stored password"); XCTAssertEqualObjects([store stringForKey:usernameKey], username, @"stored username"); XCTAssertEqualObjects([store stringForKey:passwordKey], password, @"stored password"); [UICKeyChainStore setString:nil forKey:usernameKey]; XCTAssertNil([UICKeyChainStore stringForKey:usernameKey], @"removed username"); XCTAssertEqualObjects([UICKeyChainStore stringForKey:passwordKey], password, @"left password"); XCTAssertEqualObjects([store stringForKey:passwordKey], password, @"left password"); [UICKeyChainStore setString:nil forKey:passwordKey]; XCTAssertNil([UICKeyChainStore stringForKey:usernameKey], @"removed username"); XCTAssertNil([UICKeyChainStore stringForKey:passwordKey], @"removed password"); XCTAssertNil([store stringForKey:usernameKey], @"removed username"); XCTAssertNil([store stringForKey:passwordKey], @"removed password"); } - (void)testSynchronize1 { NSString *usernameKey = @"username"; NSString *passwordKey = @"password"; NSString *username = @"kishikawakatsumi"; NSString *password = @"password1234"; NSString *serviceName = @"com.example.UICKeyChainStore"; [UICKeyChainStore removeAllItemsForService:serviceName]; UICKeyChainStore *store = [UICKeyChainStore keyChainStoreWithService:serviceName]; [store removeAllItems]; [store setString:username forKey:usernameKey]; [store setString:password forKey:passwordKey]; XCTAssertEqualObjects([store stringForKey:usernameKey], username, @"stored username"); XCTAssertEqualObjects([store stringForKey:passwordKey], password, @"stored password"); XCTAssertNil([UICKeyChainStore stringForKey:usernameKey service:serviceName], @"not synchronized yet"); XCTAssertNil([UICKeyChainStore stringForKey:passwordKey service:serviceName], @"not synchronized yet"); [store synchronize]; XCTAssertEqualObjects([store stringForKey:usernameKey], username, @"stored username"); XCTAssertEqualObjects([store stringForKey:passwordKey], password, @"stored password"); XCTAssertEqualObjects([UICKeyChainStore stringForKey:usernameKey service:serviceName], username, @"stored username"); XCTAssertEqualObjects([UICKeyChainStore stringForKey:passwordKey service:serviceName], password, @"stored password"); [store removeItemForKey:usernameKey]; XCTAssertNil([store stringForKey:usernameKey], @"removed username"); XCTAssertEqualObjects([store stringForKey:passwordKey], password, @"left password"); XCTAssertNil([UICKeyChainStore stringForKey:usernameKey service:serviceName], @"removed username"); XCTAssertEqualObjects([UICKeyChainStore stringForKey:passwordKey service:serviceName], password, @"left password"); [store removeItemForKey:passwordKey]; XCTAssertNil([store stringForKey:passwordKey], @"removed password"); XCTAssertNil([UICKeyChainStore stringForKey:passwordKey service:serviceName], @"removed password"); } - (void)testSynchronize2 { NSString *usernameKey = @"username"; NSString *passwordKey = @"password"; NSString *username = @"kishikawakatsumi"; NSString *password = @"password1234"; NSString *serviceName = @"com.example.UICKeyChainStore"; [UICKeyChainStore removeAllItemsForService:serviceName]; UICKeyChainStore *store = [UICKeyChainStore keyChainStoreWithService:serviceName]; [store removeAllItems]; [store setString:username forKey:usernameKey]; [store setString:password forKey:passwordKey]; XCTAssertEqualObjects([store stringForKey:usernameKey], username, @"stored username"); XCTAssertEqualObjects([store stringForKey:passwordKey], password, @"stored password"); XCTAssertNil([UICKeyChainStore stringForKey:usernameKey service:serviceName], @"not synchronized yet"); XCTAssertNil([UICKeyChainStore stringForKey:passwordKey service:serviceName], @"not synchronized yet"); [store removeItemForKey:usernameKey]; XCTAssertNil([store stringForKey:usernameKey], @"removed username"); XCTAssertEqualObjects([store stringForKey:passwordKey], password, @"left password"); XCTAssertNil([UICKeyChainStore stringForKey:usernameKey service:serviceName], @"not synchronized yet"); XCTAssertNil([UICKeyChainStore stringForKey:passwordKey service:serviceName], @"not synchronized yet"); [store removeItemForKey:passwordKey]; XCTAssertNil([store stringForKey:passwordKey], @"removed password"); XCTAssertNil([UICKeyChainStore stringForKey:passwordKey service:serviceName], @"not synchronized yet"); [store synchronize]; XCTAssertNil([store stringForKey:usernameKey], @"removed username"); XCTAssertNil([store stringForKey:passwordKey], @"removed password"); XCTAssertNil([UICKeyChainStore stringForKey:usernameKey service:serviceName], @"removed username"); XCTAssertNil([UICKeyChainStore stringForKey:passwordKey service:serviceName], @"removed password"); } - (void)testSynchronizeWithNoError { NSString *usernameKey = @"username"; NSString *passwordKey = @"password"; NSString *username = @"kishikawakatsumi"; NSString *password = @"password1234"; NSString *serviceName = @"com.example.UICKeyChainStore"; NSError *error; [UICKeyChainStore removeAllItemsForService:serviceName error:&error]; XCTAssertNil(error, @"no error"); UICKeyChainStore *store = [UICKeyChainStore keyChainStoreWithService:serviceName]; [store removeAllItemsWithError:&error]; XCTAssertNil(error, @"no error"); [store setString:username forKey:usernameKey error:&error]; XCTAssertNil(error, @"no error"); [store setString:password forKey:passwordKey error:&error]; XCTAssertNil(error, @"no error"); XCTAssertEqualObjects([store stringForKey:usernameKey error:&error], username, @"stored username"); XCTAssertNil(error, @"no error"); XCTAssertEqualObjects([store stringForKey:passwordKey error:&error], password, @"stored password"); XCTAssertNil(error, @"no error"); XCTAssertNil([UICKeyChainStore stringForKey:usernameKey service:serviceName error:&error], @"not synchronized yet"); XCTAssertNil(error, @"no error"); XCTAssertNil([UICKeyChainStore stringForKey:passwordKey service:serviceName error:&error], @"not synchronized yet"); XCTAssertNil(error, @"no error"); [store synchronizeWithError:&error]; XCTAssertNil(error, @"no error"); XCTAssertEqualObjects([store stringForKey:usernameKey error:&error], username, @"stored username"); XCTAssertNil(error, @"no error"); XCTAssertEqualObjects([store stringForKey:passwordKey error:&error], password, @"stored password"); XCTAssertNil(error, @"no error"); XCTAssertEqualObjects([UICKeyChainStore stringForKey:usernameKey service:serviceName error:&error], username, @"stored username"); XCTAssertNil(error, @"no error"); XCTAssertEqualObjects([UICKeyChainStore stringForKey:passwordKey service:serviceName error:&error], password, @"stored password"); XCTAssertNil(error, @"no error"); [store removeItemForKey:usernameKey error:&error]; XCTAssertNil(error, @"no error"); XCTAssertNil([store stringForKey:usernameKey error:&error], @"removed username"); XCTAssertNil(error, @"no error"); XCTAssertEqualObjects([store stringForKey:passwordKey error:&error], password, @"left password"); XCTAssertNil(error, @"no error"); XCTAssertNil([UICKeyChainStore stringForKey:usernameKey service:serviceName error:&error], @"removed username"); XCTAssertNil(error, @"no error"); XCTAssertEqualObjects([UICKeyChainStore stringForKey:passwordKey service:serviceName error:&error], password, @"left password"); XCTAssertNil(error, @"no error"); [store removeItemForKey:passwordKey error:&error]; XCTAssertNil(error, @"no error"); XCTAssertNil([store stringForKey:passwordKey error:&error], @"removed password"); XCTAssertNil(error, @"no error"); XCTAssertNil([UICKeyChainStore stringForKey:passwordKey service:serviceName error:&error], @"removed password"); XCTAssertNil(error, @"no error"); } - (void)testClassMethodsSetAndRemoveItem { // write to keychain [UICKeyChainStore setString:kStubString forKey:kStubKey]; // read from keychain, test keychain contains item NSString *actualString = [UICKeyChainStore stringForKey:kStubKey]; NSString *expectedString = kStubString; XCTAssertEqualObjects(expectedString, actualString, @"expected %@ but got %@", expectedString, actualString); // remove item from keychain [UICKeyChainStore removeItemForKey:kStubKey]; // read from keychain, test keychain doesn't contain item actualString = [UICKeyChainStore stringForKey:kStubKey]; expectedString = NULL; XCTAssertEqualObjects(expectedString, actualString, @"expected %@ but got %@", expectedString, actualString); } - (void)testClassMethodsSetAndRemoveItemWithNoError { NSError *error; [UICKeyChainStore setString:kStubString forKey:kStubKey error:&error]; XCTAssertNil(error, @"no error"); NSString *actualString = [UICKeyChainStore stringForKey:kStubKey error:&error]; XCTAssertNil(error, @"no error"); NSString *expectedString = kStubString; XCTAssertEqualObjects(expectedString, actualString, @"expected %@ but got %@", expectedString, actualString); // remove item from keychain [UICKeyChainStore removeItemForKey:kStubKey error:&error]; XCTAssertNil(error, @"no error"); // read from keychain, test keychain doesn't contain item actualString = [UICKeyChainStore stringForKey:kStubKey error:&error]; XCTAssertNil(error, @"no error"); expectedString = NULL; XCTAssertEqualObjects(expectedString, actualString, @"expected %@ but got %@", expectedString, actualString); } - (void)testInstanceMethodsSetAndRemoveItem { // create an instance UICKeyChainStore *store = [UICKeyChainStore keyChainStoreWithService:kStubService]; // write to keychain [store setString:kStubString forKey:kStubKey]; [store synchronize]; // read from keychain, test keychain contains item NSString *actualString = [store stringForKey:kStubKey]; NSString *expectedString = kStubString; XCTAssertEqualObjects(expectedString, actualString, @"expected %@ but got %@", expectedString, actualString); // remove item from keychain [store removeItemForKey:kStubKey]; [store synchronize]; // read from keychain, test keychain doesn't contain item actualString = [store stringForKey:kStubKey]; expectedString = NULL; XCTAssertEqualObjects(expectedString, actualString, @"expected %@ but got %@", expectedString, actualString); actualString = [store description]; expectedString = @"(\n)"; XCTAssertEqualObjects(expectedString, actualString, @"expected %@ but got %@", expectedString, actualString); } - (void)testInstanceMethodsSetAndRemoveItemWithNoError { NSError *error; UICKeyChainStore *store = [UICKeyChainStore keyChainStoreWithService:kStubService]; [store setString:kStubString forKey:kStubKey error:&error]; XCTAssertNil(error, @"no error"); [store synchronizeWithError:&error]; XCTAssertNil(error, @"no error"); NSString *actualString = [store stringForKey:kStubKey error:&error]; XCTAssertNil(error, @"no error"); NSString *expectedString = kStubString; XCTAssertEqualObjects(expectedString, actualString, @"expected %@ but got %@", expectedString, actualString); [store removeItemForKey:kStubKey error:&error]; XCTAssertNil(error, @"no error"); [store synchronizeWithError:&error]; XCTAssertNil(error, @"no error"); actualString = [store stringForKey:kStubKey error:&error]; XCTAssertNil(error, @"no error"); expectedString = NULL; XCTAssertEqualObjects(expectedString, actualString, @"expected %@ but got %@", expectedString, actualString); actualString = [store description]; expectedString = @"(\n)"; XCTAssertEqualObjects(expectedString, actualString, @"expected %@ but got %@", expectedString, actualString); } - (void)testInstanceMethodsSetAndRemoveWithNilValue { UICKeyChainStore *store = [UICKeyChainStore keyChainStoreWithService:kStubService]; [store setString:kStubString forKey:kStubKey]; [store synchronize]; NSString *actualString = [store stringForKey:kStubKey]; NSString *expectedString = kStubString; XCTAssertEqualObjects(expectedString, actualString, @"expected %@ but got %@", expectedString, actualString); [store setString:nil forKey:kStubKey]; [store synchronize]; actualString = [store stringForKey:kStubKey]; expectedString = NULL; XCTAssertEqualObjects(expectedString, actualString, @"expected %@ but got %@", expectedString, actualString); actualString = [store description]; expectedString = @"(\n)"; XCTAssertEqualObjects(expectedString, actualString, @"expected %@ but got %@", expectedString, actualString); } - (void)testObjectSubscripting { // create an instance UICKeyChainStore *store = [UICKeyChainStore keyChainStoreWithService:kStubService]; // write to keychain using obj subscripting store[kStubKey] = kStubString; [store synchronize]; NSString *actualString = store[kStubKey]; NSString *expectedString = kStubString; // read from keychain using obj subscripting XCTAssertEqualObjects(expectedString, actualString, @"expected %@ but got %@", expectedString, actualString); store[kStubKey] = nil; [store synchronize]; actualString = store[kStubKey]; expectedString = NULL; XCTAssertEqualObjects(expectedString, actualString, @"expected %@ but got %@", expectedString, actualString); } @end
3: 其他一参考版本
http://stackoverflow.com/questions/5247912/saving-email-password-to-keychain-in-ios
注意使用 keychain 要导入 Security.framework