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

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 = [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

时间: 2024-10-24 22:07:23

iOS 使用Keychain 保存 用户名和密码到 本地的相关文章

使用keychain保存用户名和密码等敏感信息 KeychainItemWrapper和SFHFKeychainUtils

iOS的keychain服务提供了一种安全的保存私密信息(密码,序列号,证书等)的方式,每个ios程序都有一个独立的keychain存储.相对于 NSUserDefaults.文件保存等一般方式,keychain保存更为安全,而且keychain里保存的信息不会因App被删除而丢失,所以在 重装App后,keychain里的数据还能使用.从ios 3.0开始,跨程序分享keychain变得可行. 如何需要在应用里使用使用keyChain,我们需要导入Security.framework ,key

使用keychain保存用户名和密码等敏感信息 KeychainItemWrapper和SFHFKeychainUtils。

iOS的keychain服务提供了一种安全的保存私密信息(密码,序列号,证书等)的方式,每个ios程序都有一个独立的keychain存储.相对于NSUserDefaults.文件保存等一般方式,keychain保存更为安全,而且keychain里保存的信息不会因App被删除而丢失,所以在重装App后,keychain里的数据还能使用.从ios 3.0开始,跨程序分享keychain变得可行. 如何需要在应用里使用使用keyChain,我们需要导入Security.framework ,keych

iOS开发,使用keychain保存用户名密码

本文提供完整版demo,源码下载地址:GitHub Demo下载 KeyChain是苹果提供的一种安全的保存用户名.密码.证书的方式,将敏感信息保存在keychain中后,这些信息不会随着app的卸载而丢失,除非开发人员在app中手动删除敏感信息,否则,这些信息将会一直保存在keychain中. 在使用keychain时,我们首先要将security.framework引入到工程中.由于使用时不支持arc,所以我们在arc环境中需要针对相关文件启用mrc模式. 首先,我们构造一个工具类,通过这个

android 保存 用户名和密码 设置等应用信息优化

1.传统的保存用户名,密码方式 SharedPreferences Editor editor = shareReference.edit(); editor.putString(KEY_NAME,"username_value"); 通过这样的方法,能够基本满足需求,比如有用户名,那么就Editor.putString存放就好. 但是这样的方法有一些弊端: (1)在存放一些集合信息,存储ArrayList就不合适 (2)如果针对用户,新增加了很多熟悉,比如性别,头像等信息,那么需要一

Android简易实战教程--第十六话《SharedPreferences保存用户名和密码》

之前在Android简易实战教程--第七话<在内存中存储用户名和密码> 那里是把用户名和密码保存到了内存中,这一篇把用户名和密码保存至SharedPreferences文件.为了引起误导,声明实际开发中不会用到这两种方式,这里指示提供一种思路和给初学者学习简单的api. 由于内容和之前的基本一样,不做过多的解释.直接上代码: xml文件: <LinearLayout xmlns:android="http://schemas.android.com/apk/res/androi

Android保存用户名和密码

我们不管在开发一个项目或者使用别人的项目,都有用户登录功能,为了让用户的体验效果更好,我们通常会做一个功能,叫做保存用户,这样做的目地就是为了让用户下一次再使用该程序不会重新输入用户名和密码,这里我使用3种方式来存储用户名和密码 1.通过普通 的txt文本存储 2.通过properties属性文件进行存储 3.通过SharedPreferences工具类存储 第一种: /** * 保存用户名和密码的业务方法 * * @param username * @param password * @ret

IOS开发之----两种保存用户名和密码实现记住密码库

使用Keychain存储用户敏感信息 iOS的keychain服务提供了一种安全的保存私密信息(密码,序列号,证书等)的方式,每个ios程序都有一个独立的keychain存储.相对于 NSUserDefaults.文件保存等一般方式,keychain保存更为安全,而且keychain里保存的信息不会因App被删除而丢失,所以在 重装App后,keychain里的数据还能使用.从ios 3.0开始,跨程序分享keychain变得可行. 如何需要在应用里使用使用keyChain,我们需要导入Secu

KIKeyChain 安全保存用户名和密码

在 iOS 应用程序开发过程中,我们经常会存储一些比较重要的信息.如涉及到用户系统的 App, 我们就需要考虑自动登录的功能,如果把用户的用户名和密码存储在 NSUserDefault 中很不安全.第一,该信息是明文存储的:第二,可以通过一些工具获取到 NSUserDefault 中的信息.容易造成泄露用户的账号信息.出于安全方面的考虑,Apple 为我们提供了一个叫 KeyChain 的工具, 存储在里面的信息不能说绝对安全,但是相对于 NSUserDefault 或者其它一些存储在 App

终于解决“Git Windows客户端保存用户名与密码”的问题

Git - How to use netrc file on windows - Stack Overflow 这就是正确答案,我们已经验证过了,下面详细描述一下解决方法: 1. 在Windows中添加一个HOME环境变量,值为%USERPROFILE%,如下图: 2. 在"开始>运行"中打开%Home%,新建一个名为"_netrc"的文件. 3. 用记事本打开_netrc文件,输入Git服务器名.用户名.密码,并保存.示例如下: machine git.cn