首页 > 代码库 > iOS 使用Keychain 保存 用户名和密码到 本地

iOS 使用Keychain 保存 用户名和密码到 本地

iOS 使用Keychain 保存 用户名和密码到 本地

之前曾把一些简单的数据保存在了plist,文件,及NsuserDefault里面,

但是如果要保存密码之类的,保存在本地就很不安全了;

但是利用 Keychain 我们可以很安全的把 用户密码等信息保存在本地

1:使用苹果官方封装好的Keychain操作类

   GenericKeychain

2:使用 开源的keychain操作

   sskeychain

技术分享
#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
View Code

 

  UICKeyChainStore

 

技术分享
#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 =http://www.mamicode.com/ [username dataUsingEncoding:NSUTF8StringEncoding];    NSData *passwordData =http://www.mamicode.com/ [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 =http://www.mamicode.com/ [username dataUsingEncoding:NSUTF8StringEncoding];    NSData *passwordData =http://www.mamicode.com/ [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 =http://www.mamicode.com/ [username dataUsingEncoding:NSUTF8StringEncoding];    NSData *passwordData =http://www.mamicode.com/ [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
View Code

 

3: 其他一参考版本

http://stackoverflow.com/questions/5247912/saving-email-password-to-keychain-in-ios

 

注意使用 keychain 要导入 Security.framework

 

iOS 使用Keychain 保存 用户名和密码到 本地