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

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

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

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

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

GenericKeychain

2:使用 开源的keychain操作

sskeychain

  1. #import <XCTest/XCTest.h>
  2. #import "SSKeychain.h"
  3.  
  4. static NSString *const kSSKeychainServiceName = @"SSToolkitTestService";
  5. static NSString *const kSSKeychainAccountName = @"SSToolkitTestAccount";
  6. static NSString *const kSSKeychainPassword = @"SSToolkitTestPassword";
  7. static NSString *const kSSKeychainLabel = @"SSToolkitLabel";
  8.  
  9. @interface SSKeychainTests : XCTestCase
  10. @end
  11.  
  12. @implementation SSKeychainTests
  13.  
  14. - (void)testNewItem {
  15. // New item
  16. SSKeychainQuery *query = [[SSKeychainQuery alloc] init];
  17. query.password = kSSKeychainPassword;
  18. query.service = kSSKeychainServiceName;
  19. query.account = kSSKeychainAccountName;
  20. query.label = kSSKeychainLabel;
  21.  
  22. NSError *error;
  23. XCTAssertTrue([query save:&error], @"Unable to save item: %@", error);
  24.  
  25. // Look up
  26. query = [[SSKeychainQuery alloc] init];
  27. query.service = kSSKeychainServiceName;
  28. query.account = kSSKeychainAccountName;
  29. query.password = nil;
  30.  
  31. XCTAssertTrue([query fetch:&error], @"Unable to fetch keychain item: %@", error);
  32. XCTAssertEqualObjects(query.password, kSSKeychainPassword, @"Passwords were not equal");
  33.  
  34. // Search for all accounts
  35. query = [[SSKeychainQuery alloc] init];
  36. NSArray *accounts = [query fetchAll:&error];
  37. XCTAssertNotNil(accounts, @"Unable to fetch accounts: %@", error);
  38. XCTAssertTrue([self _accounts:accounts containsAccountWithName:kSSKeychainAccountName], @"Matching account was not returned");
  39.  
  40. // Check accounts for service
  41. query.service = kSSKeychainServiceName;
  42. accounts = [query fetchAll:&error];
  43. XCTAssertNotNil(accounts, @"Unable to fetch accounts: %@", error);
  44. XCTAssertTrue([self _accounts:accounts containsAccountWithName:kSSKeychainAccountName], @"Matching account was not returned");
  45.  
  46. // Delete
  47. query = [[SSKeychainQuery alloc] init];
  48. query.service = kSSKeychainServiceName;
  49. query.account = kSSKeychainAccountName;
  50. XCTAssertTrue([query deleteItem:&error], @"Unable to delete password: %@", error);
  51. }
  52.  
  53. - (void)testPasswordObject {
  54. SSKeychainQuery *query = [[SSKeychainQuery alloc] init];
  55. query.service = kSSKeychainServiceName;
  56. query.account = kSSKeychainAccountName;
  57.  
  58. NSDictionary *dictionary = @{@"number": @, @"string": @"Hello World"};
  59. query.passwordObject = dictionary;
  60.  
  61. NSError *error;
  62. XCTAssertTrue([query save:&error], @"Unable to save item: %@", error);
  63.  
  64. query = [[SSKeychainQuery alloc] init];
  65. query.service = kSSKeychainServiceName;
  66. query.account = kSSKeychainAccountName;
  67. query.passwordObject = nil;
  68. XCTAssertTrue([query fetch:&error], @"Unable to fetch keychain item: %@", error);
  69. XCTAssertEqualObjects(query.passwordObject, dictionary, @"Passwords were not equal");
  70. }
  71.  
  72. - (void)testMissingInformation {
  73. SSKeychainQuery *query = [[SSKeychainQuery alloc] init];
  74. query.service = kSSKeychainServiceName;
  75. query.account = kSSKeychainAccountName;
  76.  
  77. NSError *error;
  78. XCTAssertFalse([query save:&error], @"Function should return NO as not all needed information is provided: %@", error);
  79.  
  80. query = [[SSKeychainQuery alloc] init];
  81. query.password = kSSKeychainPassword;
  82. query.account = kSSKeychainAccountName;
  83. XCTAssertFalse([query save:&error], @"Function should return NO as not all needed information is provided: %@", error);
  84.  
  85. query = [[SSKeychainQuery alloc] init];
  86. query.password = kSSKeychainPassword;
  87. query.service = kSSKeychainServiceName;
  88. XCTAssertFalse([query save:&error], @"Function save should return NO if not all needed information is provided: %@", error);
  89. }
  90.  
  91. - (void)testDeleteWithMissingInformation {
  92. SSKeychainQuery *query = [[SSKeychainQuery alloc] init];
  93. query.account = kSSKeychainAccountName;
  94.  
  95. NSError *error;
  96. XCTAssertFalse([query deleteItem:&error], @"Function deleteItem should return NO if not all needed information is provided: %@", error);
  97.  
  98. query = [[SSKeychainQuery alloc] init];
  99. query.service = kSSKeychainServiceName;
  100. XCTAssertFalse([query deleteItem:&error], @"Function deleteItem should return NO if not all needed information is provided: %@", error);
  101.  
  102. // check if fetch handels missing information correctly
  103. query = [[SSKeychainQuery alloc] init];
  104. query.account = kSSKeychainAccountName;
  105. XCTAssertFalse([query fetch:&error], @"Function fetch should return NO if not all needed information is provided: %@", error);
  106.  
  107. query = [[SSKeychainQuery alloc] init];
  108. query.service = kSSKeychainServiceName;
  109. XCTAssertFalse([query fetch:&error], @"Function fetch should return NO if not all needed information is provided: %@", error);
  110.  
  111. query = [[SSKeychainQuery alloc] init];
  112. query.service = kSSKeychainServiceName;
  113. XCTAssertFalse([query fetch:NULL], @"Function fetch should return NO if not all needed information is provided and error is NULL");
  114. }
  115.  
  116. - (void)testSynchronizable {
  117. SSKeychainQuery *query = [[SSKeychainQuery alloc] init];
  118. query.service = kSSKeychainServiceName;
  119. query.account = kSSKeychainAccountName;
  120. query.password = kSSKeychainPassword;
  121. query.synchronizationMode = SSKeychainQuerySynchronizationModeYes;
  122.  
  123. NSError *error;
  124. XCTAssertTrue([query save:&error], @"Unable to save item: %@", error);
  125.  
  126. query = [[SSKeychainQuery alloc] init];
  127. query.service = kSSKeychainServiceName;
  128. query.account = kSSKeychainAccountName;
  129. query.password = nil;
  130. query.synchronizationMode = SSKeychainQuerySynchronizationModeNo;
  131. XCTAssertFalse([query fetch:&error], @"Fetch should fail when trying to fetch an unsynced password that was saved as synced: %@", error);
  132. XCTAssertFalse([query fetch:NULL], @"Fetch should fail when trying to fetch an unsynced password that was saved as synced. error == NULL");
  133.  
  134. XCTAssertNotEqualObjects(query.password, kSSKeychainPassword, @"Passwords should not be equal when trying to fetch an unsynced password that was saved as synced.");
  135.  
  136. query = [[SSKeychainQuery alloc] init];
  137. query.service = kSSKeychainServiceName;
  138. query.account = kSSKeychainAccountName;
  139. query.password = nil;
  140. query.synchronizationMode = SSKeychainQuerySynchronizationModeAny;
  141. XCTAssertTrue([query fetch:&error], @"Unable to fetch keychain item: %@", error);
  142. XCTAssertEqualObjects(query.password, kSSKeychainPassword, @"Passwords were not equal");
  143. }
  144.  
  145. // Test Class Methods of SSKeychain
  146. - (void)testSSKeychain {
  147. NSError *error = nil;
  148.  
  149. // create a new keychain item
  150. XCTAssertTrue([SSKeychain setPassword:kSSKeychainPassword forService:kSSKeychainServiceName account:kSSKeychainAccountName error:&error], @"Unable to save item: %@", error);
  151.  
  152. // check password
  153. XCTAssertEqualObjects([SSKeychain passwordForService:kSSKeychainServiceName account:kSSKeychainAccountName], kSSKeychainPassword, @"Passwords were not equal");
  154.  
  155. // check all accounts
  156. XCTAssertTrue([self _accounts:[SSKeychain allAccounts] containsAccountWithName:kSSKeychainAccountName], @"Matching account was not returned");
  157. // check account
  158. XCTAssertTrue([self _accounts:[SSKeychain accountsForService:kSSKeychainServiceName] containsAccountWithName:kSSKeychainAccountName], @"Matching account was not returned");
  159.  
  160. // delete password
  161. XCTAssertTrue([SSKeychain deletePasswordForService:kSSKeychainServiceName account:kSSKeychainAccountName error:&error], @"Unable to delete password: %@", error);
  162.  
  163. // set password and delete it without error function
  164. XCTAssertTrue([SSKeychain setPassword:kSSKeychainPassword forService:kSSKeychainServiceName account:kSSKeychainAccountName], @"Unable to save item");
  165. XCTAssertTrue([SSKeychain deletePasswordForService:kSSKeychainServiceName account:kSSKeychainAccountName], @"Unable to delete password");
  166.  
  167. #if __IPHONE_4_0 && TARGET_OS_IPHONE
  168. [SSKeychain setAccessibilityType:kSecAttrAccessibleWhenUnlockedThisDeviceOnly];
  169. XCTAssertTrue([SSKeychain accessibilityType] == kSecAttrAccessibleWhenUnlockedThisDeviceOnly, @"Unable to verify accessibilityType");
  170. #endif
  171. }
  172.  
  173. #pragma mark - Private
  174.  
  175. - (BOOL)_accounts:(NSArray *)accounts containsAccountWithName:(NSString *)name {
  176. for (NSDictionary *dictionary in accounts) {
  177. if ([[dictionary objectForKey:@"acct"] isEqualToString:name]) {
  178. return YES;
  179. }
  180. }
  181. return NO;
  182. }
  183.  
  184. @end

UICKeyChainStore

  1. #import <XCTest/XCTest.h>
  2. #import "UICKeyChainStore.h"
  3.  
  4. @interface UICKeyChainStoreTests : XCTestCase {
  5. NSString *kStubKey;
  6. NSString *kStubString;
  7. NSString *kStubService;
  8. }
  9.  
  10. @end
  11.  
  12. @implementation UICKeyChainStoreTests
  13.  
  14. - (void)setUp
  15. {
  16. [super setUp];
  17.  
  18. kStubKey = @"password";
  19. kStubString = @"password1234";
  20. kStubService = @"com.kishikawakatsumi";
  21.  
  22. [UICKeyChainStore setDefaultService:kStubService];
  23.  
  24. [UICKeyChainStore removeAllItems];
  25. }
  26.  
  27. - (void)tearDown
  28. {
  29. [super tearDown];
  30. }
  31.  
  32. - (void)testSetDefaultService
  33. {
  34. NSString *serviceName = @"com.kishikawakatsumi.UICKeyChainStore";
  35. [UICKeyChainStore setDefaultService:serviceName];
  36. XCTAssertEqualObjects(serviceName, [UICKeyChainStore defaultService], @"specitfy default service name");
  37. }
  38.  
  39. - (void)testInitializers
  40. {
  41. UICKeyChainStore *store = nil;
  42.  
  43. store = [UICKeyChainStore keyChainStore];
  44. XCTAssertEqualObjects(store.service, [UICKeyChainStore defaultService], @"instantiate default store");
  45.  
  46. store = [[UICKeyChainStore alloc] init];
  47. XCTAssertEqualObjects(store.service, [UICKeyChainStore defaultService], @"instantiate default store");
  48.  
  49. NSString *serviceName = @"com.kishikawakatsumi.UICKeyChainStore";
  50. store = [UICKeyChainStore keyChainStoreWithService:serviceName];
  51. XCTAssertEqualObjects(store.service, serviceName, @"instantiate custom service named store");
  52. }
  53.  
  54. - (void)testSetData
  55. {
  56. NSString *usernameKey = @"username";
  57. NSString *passwordKey = @"password";
  58. NSString *username = @"kishikawakatsumi";
  59. NSString *password = @"password1234";
  60. NSData *usernameData = [username dataUsingEncoding:NSUTF8StringEncoding];
  61. NSData *passwordData = [password dataUsingEncoding:NSUTF8StringEncoding];
  62.  
  63. [UICKeyChainStore setData:[username dataUsingEncoding:NSUTF8StringEncoding] forKey:usernameKey];
  64. [UICKeyChainStore setData:[password dataUsingEncoding:NSUTF8StringEncoding] forKey:passwordKey];
  65. XCTAssertEqualObjects([UICKeyChainStore dataForKey:usernameKey], usernameData, @"stored username");
  66. XCTAssertEqualObjects([UICKeyChainStore dataForKey:passwordKey], passwordData, @"stored password");
  67.  
  68. [UICKeyChainStore removeItemForKey:usernameKey service:[UICKeyChainStore defaultService]];
  69. XCTAssertNil([UICKeyChainStore dataForKey:usernameKey], @"removed username");
  70. XCTAssertEqualObjects([UICKeyChainStore dataForKey:passwordKey], passwordData, @"left password");
  71.  
  72. [UICKeyChainStore removeItemForKey:passwordKey service:[UICKeyChainStore defaultService]];
  73. XCTAssertNil([UICKeyChainStore dataForKey:usernameKey], @"removed username");
  74. XCTAssertNil([UICKeyChainStore dataForKey:passwordKey], @"removed password");
  75. }
  76.  
  77. - (void)testSetDataWithNoError
  78. {
  79. NSString *usernameKey = @"username";
  80. NSString *passwordKey = @"password";
  81. NSString *username = @"kishikawakatsumi";
  82. NSString *password = @"password1234";
  83. NSData *usernameData = [username dataUsingEncoding:NSUTF8StringEncoding];
  84. NSData *passwordData = [password dataUsingEncoding:NSUTF8StringEncoding];
  85.  
  86. NSError *error;
  87.  
  88. [UICKeyChainStore setData:[username dataUsingEncoding:NSUTF8StringEncoding] forKey:usernameKey error:&error];
  89. XCTAssertNil(error, @"no error");
  90. XCTAssertEqualObjects([UICKeyChainStore dataForKey:usernameKey error:&error], usernameData, @"stored username");
  91. XCTAssertNil(error, @"no error");
  92.  
  93. [UICKeyChainStore setData:[password dataUsingEncoding:NSUTF8StringEncoding] forKey:passwordKey error:&error];
  94. XCTAssertNil(error, @"no error");
  95. XCTAssertEqualObjects([UICKeyChainStore dataForKey:passwordKey error:&error], passwordData, @"stored password");
  96. XCTAssertNil(error, @"no error");
  97.  
  98. [UICKeyChainStore removeItemForKey:usernameKey service:[UICKeyChainStore defaultService] error:&error];
  99. XCTAssertNil(error, @"no error");
  100. XCTAssertNil([UICKeyChainStore dataForKey:usernameKey error:&error], @"removed username");
  101. XCTAssertNil(error, @"no error");
  102. XCTAssertEqualObjects([UICKeyChainStore dataForKey:passwordKey error:&error], passwordData, @"left password");
  103. XCTAssertNil(error, @"no error");
  104.  
  105. [UICKeyChainStore removeItemForKey:passwordKey service:[UICKeyChainStore defaultService] error:&error];
  106. XCTAssertNil(error, @"no error");
  107. XCTAssertNil([UICKeyChainStore dataForKey:usernameKey error:&error], @"removed username");
  108. XCTAssertNil(error, @"no error");
  109. XCTAssertNil([UICKeyChainStore dataForKey:passwordKey error:&error], @"removed password");
  110. XCTAssertNil(error, @"no error");
  111. }
  112.  
  113. - (void)testSetNilData
  114. {
  115. NSString *usernameKey = @"username";
  116. NSString *passwordKey = @"password";
  117. NSString *username = @"kishikawakatsumi";
  118. NSString *password = @"password1234";
  119. NSData *usernameData = [username dataUsingEncoding:NSUTF8StringEncoding];
  120. NSData *passwordData = [password dataUsingEncoding:NSUTF8StringEncoding];
  121.  
  122. [UICKeyChainStore setData:nil forKey:usernameKey];
  123. [UICKeyChainStore setData:nil forKey:passwordKey];
  124. XCTAssertNil([UICKeyChainStore dataForKey:usernameKey], @"no username");
  125. XCTAssertNil([UICKeyChainStore dataForKey:passwordKey], @"no password");
  126.  
  127. [UICKeyChainStore setData:[username dataUsingEncoding:NSUTF8StringEncoding] forKey:usernameKey];
  128. [UICKeyChainStore setData:[password dataUsingEncoding:NSUTF8StringEncoding] forKey:passwordKey];
  129. XCTAssertEqualObjects([UICKeyChainStore dataForKey:usernameKey], usernameData, @"stored username");
  130. XCTAssertEqualObjects([UICKeyChainStore dataForKey:passwordKey], passwordData, @"stored password");
  131.  
  132. [UICKeyChainStore setData:nil forKey:usernameKey];
  133. XCTAssertNil([UICKeyChainStore dataForKey:usernameKey], @"removed username");
  134. XCTAssertEqualObjects([UICKeyChainStore dataForKey:passwordKey], passwordData, @"left password");
  135.  
  136. [UICKeyChainStore setData:nil forKey:passwordKey];
  137. XCTAssertNil([UICKeyChainStore dataForKey:usernameKey], @"removed username");
  138. XCTAssertNil([UICKeyChainStore dataForKey:passwordKey], @"removed password");
  139.  
  140. [UICKeyChainStore removeItemForKey:usernameKey];
  141. XCTAssertNil([UICKeyChainStore dataForKey:usernameKey], @"removed username");
  142. XCTAssertNil([UICKeyChainStore dataForKey:passwordKey], @"removed password");
  143.  
  144. [UICKeyChainStore removeItemForKey:passwordKey];
  145. XCTAssertNil([UICKeyChainStore dataForKey:usernameKey], @"removed username");
  146. XCTAssertNil([UICKeyChainStore dataForKey:passwordKey], @"removed password");
  147. }
  148.  
  149. - (void)testSetUsernameAndPassword
  150. {
  151. NSString *usernameKey = @"username";
  152. NSString *passwordKey = @"password";
  153. NSString *username = @"kishikawakatsumi";
  154. NSString *password = @"password1234";
  155.  
  156. UICKeyChainStore *store = [UICKeyChainStore keyChainStore];
  157. [store removeAllItems];
  158.  
  159. [UICKeyChainStore setString:username forKey:usernameKey];
  160. [UICKeyChainStore setString:password forKey:passwordKey];
  161. XCTAssertEqualObjects([UICKeyChainStore stringForKey:usernameKey], username, @"stored username");
  162. XCTAssertEqualObjects([UICKeyChainStore stringForKey:passwordKey], password, @"stored password");
  163. XCTAssertEqualObjects([store stringForKey:usernameKey], username, @"stored username");
  164. XCTAssertEqualObjects([store stringForKey:passwordKey], password, @"stored password");
  165.  
  166. [UICKeyChainStore removeItemForKey:usernameKey];
  167. XCTAssertNil([UICKeyChainStore stringForKey:usernameKey], @"removed username");
  168. XCTAssertEqualObjects([UICKeyChainStore stringForKey:passwordKey], password, @"left password");
  169. XCTAssertEqualObjects([store stringForKey:passwordKey], password, @"left password");
  170.  
  171. [UICKeyChainStore removeItemForKey:passwordKey];
  172. XCTAssertNil([UICKeyChainStore stringForKey:usernameKey], @"removed username");
  173. XCTAssertNil([UICKeyChainStore stringForKey:passwordKey], @"removed password");
  174. XCTAssertNil([store stringForKey:usernameKey], @"removed username");
  175. XCTAssertNil([store stringForKey:passwordKey], @"removed password");
  176. }
  177.  
  178. - (void)testSetUsernameAndPasswordWithNoError
  179. {
  180. NSString *usernameKey = @"username";
  181. NSString *passwordKey = @"password";
  182. NSString *username = @"kishikawakatsumi";
  183. NSString *password = @"password1234";
  184.  
  185. NSError *error;
  186.  
  187. UICKeyChainStore *store = [UICKeyChainStore keyChainStore];
  188. [store removeAllItemsWithError:&error];
  189. XCTAssertNil(error, @"no error");
  190.  
  191. [UICKeyChainStore setString:username forKey:usernameKey error:&error];
  192. XCTAssertNil(error, @"no error");
  193. [UICKeyChainStore setString:password forKey:passwordKey error:&error];
  194. XCTAssertNil(error, @"no error");
  195.  
  196. XCTAssertEqualObjects([UICKeyChainStore stringForKey:usernameKey error:&error], username, @"stored username");
  197. XCTAssertNil(error, @"no error");
  198. XCTAssertEqualObjects([UICKeyChainStore stringForKey:passwordKey error:&error], password, @"stored password");
  199. XCTAssertNil(error, @"no error");
  200.  
  201. XCTAssertEqualObjects([store stringForKey:usernameKey error:&error], username, @"stored username");
  202. XCTAssertNil(error, @"no error");
  203. XCTAssertEqualObjects([store stringForKey:passwordKey error:&error], password, @"stored password");
  204. XCTAssertNil(error, @"no error");
  205.  
  206. [UICKeyChainStore removeItemForKey:usernameKey error:&error];
  207. XCTAssertNil(error, @"no error");
  208. XCTAssertNil([UICKeyChainStore stringForKey:usernameKey error:&error], @"removed username");
  209. XCTAssertNil(error, @"no error");
  210. XCTAssertEqualObjects([UICKeyChainStore stringForKey:passwordKey error:&error], password, @"left password");
  211. XCTAssertNil(error, @"no error");
  212. XCTAssertEqualObjects([store stringForKey:passwordKey error:&error], password, @"left password");
  213. XCTAssertNil(error, @"no error");
  214.  
  215. [UICKeyChainStore removeItemForKey:passwordKey error:&error];
  216. XCTAssertNil(error, @"no error");
  217. XCTAssertNil([UICKeyChainStore stringForKey:usernameKey error:&error], @"removed username");
  218. XCTAssertNil(error, @"no error");
  219. XCTAssertNil([UICKeyChainStore stringForKey:passwordKey error:&error], @"removed password");
  220. XCTAssertNil(error, @"no error");
  221. XCTAssertNil([store stringForKey:usernameKey error:&error], @"removed username");
  222. XCTAssertNil(error, @"no error");
  223. XCTAssertNil([store stringForKey:passwordKey error:&error], @"removed password");
  224. XCTAssertNil(error, @"no error");
  225. }
  226.  
  227. - (void)testSetNilUsernameAndNilPassword
  228. {
  229. NSString *usernameKey = @"username";
  230. NSString *passwordKey = @"password";
  231. NSString *username = @"kishikawakatsumi";
  232. NSString *password = @"password1234";
  233.  
  234. UICKeyChainStore *store = [UICKeyChainStore keyChainStore];
  235. [store removeAllItems];
  236.  
  237. [UICKeyChainStore setString:nil forKey:usernameKey];
  238. [UICKeyChainStore setString:nil forKey:passwordKey];
  239. XCTAssertNil([UICKeyChainStore dataForKey:usernameKey], @"no username");
  240. XCTAssertNil([UICKeyChainStore dataForKey:passwordKey], @"no password");
  241.  
  242. [UICKeyChainStore setString:username forKey:usernameKey];
  243. [UICKeyChainStore setString:password forKey:passwordKey];
  244. XCTAssertEqualObjects([UICKeyChainStore stringForKey:usernameKey], username, @"stored username");
  245. XCTAssertEqualObjects([UICKeyChainStore stringForKey:passwordKey], password, @"stored password");
  246. XCTAssertEqualObjects([store stringForKey:usernameKey], username, @"stored username");
  247. XCTAssertEqualObjects([store stringForKey:passwordKey], password, @"stored password");
  248.  
  249. [UICKeyChainStore setString:nil forKey:usernameKey];
  250. XCTAssertNil([UICKeyChainStore stringForKey:usernameKey], @"removed username");
  251. XCTAssertEqualObjects([UICKeyChainStore stringForKey:passwordKey], password, @"left password");
  252. XCTAssertEqualObjects([store stringForKey:passwordKey], password, @"left password");
  253.  
  254. [UICKeyChainStore setString:nil forKey:passwordKey];
  255. XCTAssertNil([UICKeyChainStore stringForKey:usernameKey], @"removed username");
  256. XCTAssertNil([UICKeyChainStore stringForKey:passwordKey], @"removed password");
  257. XCTAssertNil([store stringForKey:usernameKey], @"removed username");
  258. XCTAssertNil([store stringForKey:passwordKey], @"removed password");
  259. }
  260.  
  261. - (void)testSynchronize1
  262. {
  263. NSString *usernameKey = @"username";
  264. NSString *passwordKey = @"password";
  265. NSString *username = @"kishikawakatsumi";
  266. NSString *password = @"password1234";
  267.  
  268. NSString *serviceName = @"com.example.UICKeyChainStore";
  269. [UICKeyChainStore removeAllItemsForService:serviceName];
  270.  
  271. UICKeyChainStore *store = [UICKeyChainStore keyChainStoreWithService:serviceName];
  272. [store removeAllItems];
  273.  
  274. [store setString:username forKey:usernameKey];
  275. [store setString:password forKey:passwordKey];
  276. XCTAssertEqualObjects([store stringForKey:usernameKey], username, @"stored username");
  277. XCTAssertEqualObjects([store stringForKey:passwordKey], password, @"stored password");
  278. XCTAssertNil([UICKeyChainStore stringForKey:usernameKey service:serviceName], @"not synchronized yet");
  279. XCTAssertNil([UICKeyChainStore stringForKey:passwordKey service:serviceName], @"not synchronized yet");
  280.  
  281. [store synchronize];
  282. XCTAssertEqualObjects([store stringForKey:usernameKey], username, @"stored username");
  283. XCTAssertEqualObjects([store stringForKey:passwordKey], password, @"stored password");
  284. XCTAssertEqualObjects([UICKeyChainStore stringForKey:usernameKey service:serviceName], username, @"stored username");
  285. XCTAssertEqualObjects([UICKeyChainStore stringForKey:passwordKey service:serviceName], password, @"stored password");
  286.  
  287. [store removeItemForKey:usernameKey];
  288. XCTAssertNil([store stringForKey:usernameKey], @"removed username");
  289. XCTAssertEqualObjects([store stringForKey:passwordKey], password, @"left password");
  290. XCTAssertNil([UICKeyChainStore stringForKey:usernameKey service:serviceName], @"removed username");
  291. XCTAssertEqualObjects([UICKeyChainStore stringForKey:passwordKey service:serviceName], password, @"left password");
  292.  
  293. [store removeItemForKey:passwordKey];
  294. XCTAssertNil([store stringForKey:passwordKey], @"removed password");
  295. XCTAssertNil([UICKeyChainStore stringForKey:passwordKey service:serviceName], @"removed password");
  296. }
  297.  
  298. - (void)testSynchronize2
  299. {
  300. NSString *usernameKey = @"username";
  301. NSString *passwordKey = @"password";
  302. NSString *username = @"kishikawakatsumi";
  303. NSString *password = @"password1234";
  304.  
  305. NSString *serviceName = @"com.example.UICKeyChainStore";
  306. [UICKeyChainStore removeAllItemsForService:serviceName];
  307.  
  308. UICKeyChainStore *store = [UICKeyChainStore keyChainStoreWithService:serviceName];
  309. [store removeAllItems];
  310.  
  311. [store setString:username forKey:usernameKey];
  312. [store setString:password forKey:passwordKey];
  313. XCTAssertEqualObjects([store stringForKey:usernameKey], username, @"stored username");
  314. XCTAssertEqualObjects([store stringForKey:passwordKey], password, @"stored password");
  315. XCTAssertNil([UICKeyChainStore stringForKey:usernameKey service:serviceName], @"not synchronized yet");
  316. XCTAssertNil([UICKeyChainStore stringForKey:passwordKey service:serviceName], @"not synchronized yet");
  317.  
  318. [store removeItemForKey:usernameKey];
  319. XCTAssertNil([store stringForKey:usernameKey], @"removed username");
  320. XCTAssertEqualObjects([store stringForKey:passwordKey], password, @"left password");
  321. XCTAssertNil([UICKeyChainStore stringForKey:usernameKey service:serviceName], @"not synchronized yet");
  322. XCTAssertNil([UICKeyChainStore stringForKey:passwordKey service:serviceName], @"not synchronized yet");
  323.  
  324. [store removeItemForKey:passwordKey];
  325. XCTAssertNil([store stringForKey:passwordKey], @"removed password");
  326. XCTAssertNil([UICKeyChainStore stringForKey:passwordKey service:serviceName], @"not synchronized yet");
  327.  
  328. [store synchronize];
  329.  
  330. XCTAssertNil([store stringForKey:usernameKey], @"removed username");
  331. XCTAssertNil([store stringForKey:passwordKey], @"removed password");
  332. XCTAssertNil([UICKeyChainStore stringForKey:usernameKey service:serviceName], @"removed username");
  333. XCTAssertNil([UICKeyChainStore stringForKey:passwordKey service:serviceName], @"removed password");
  334. }
  335.  
  336. - (void)testSynchronizeWithNoError
  337. {
  338. NSString *usernameKey = @"username";
  339. NSString *passwordKey = @"password";
  340. NSString *username = @"kishikawakatsumi";
  341. NSString *password = @"password1234";
  342.  
  343. NSString *serviceName = @"com.example.UICKeyChainStore";
  344.  
  345. NSError *error;
  346.  
  347. [UICKeyChainStore removeAllItemsForService:serviceName error:&error];
  348. XCTAssertNil(error, @"no error");
  349.  
  350. UICKeyChainStore *store = [UICKeyChainStore keyChainStoreWithService:serviceName];
  351. [store removeAllItemsWithError:&error];
  352. XCTAssertNil(error, @"no error");
  353.  
  354. [store setString:username forKey:usernameKey error:&error];
  355. XCTAssertNil(error, @"no error");
  356. [store setString:password forKey:passwordKey error:&error];
  357. XCTAssertNil(error, @"no error");
  358. XCTAssertEqualObjects([store stringForKey:usernameKey error:&error], username, @"stored username");
  359. XCTAssertNil(error, @"no error");
  360. XCTAssertEqualObjects([store stringForKey:passwordKey error:&error], password, @"stored password");
  361. XCTAssertNil(error, @"no error");
  362. XCTAssertNil([UICKeyChainStore stringForKey:usernameKey service:serviceName error:&error], @"not synchronized yet");
  363. XCTAssertNil(error, @"no error");
  364. XCTAssertNil([UICKeyChainStore stringForKey:passwordKey service:serviceName error:&error], @"not synchronized yet");
  365. XCTAssertNil(error, @"no error");
  366.  
  367. [store synchronizeWithError:&error];
  368. XCTAssertNil(error, @"no error");
  369. XCTAssertEqualObjects([store stringForKey:usernameKey error:&error], username, @"stored username");
  370. XCTAssertNil(error, @"no error");
  371. XCTAssertEqualObjects([store stringForKey:passwordKey error:&error], password, @"stored password");
  372. XCTAssertNil(error, @"no error");
  373. XCTAssertEqualObjects([UICKeyChainStore stringForKey:usernameKey service:serviceName error:&error], username, @"stored username");
  374. XCTAssertNil(error, @"no error");
  375. XCTAssertEqualObjects([UICKeyChainStore stringForKey:passwordKey service:serviceName error:&error], password, @"stored password");
  376. XCTAssertNil(error, @"no error");
  377.  
  378. [store removeItemForKey:usernameKey error:&error];
  379. XCTAssertNil(error, @"no error");
  380. XCTAssertNil([store stringForKey:usernameKey error:&error], @"removed username");
  381. XCTAssertNil(error, @"no error");
  382. XCTAssertEqualObjects([store stringForKey:passwordKey error:&error], password, @"left password");
  383. XCTAssertNil(error, @"no error");
  384. XCTAssertNil([UICKeyChainStore stringForKey:usernameKey service:serviceName error:&error], @"removed username");
  385. XCTAssertNil(error, @"no error");
  386. XCTAssertEqualObjects([UICKeyChainStore stringForKey:passwordKey service:serviceName error:&error], password, @"left password");
  387. XCTAssertNil(error, @"no error");
  388.  
  389. [store removeItemForKey:passwordKey error:&error];
  390. XCTAssertNil(error, @"no error");
  391. XCTAssertNil([store stringForKey:passwordKey error:&error], @"removed password");
  392. XCTAssertNil(error, @"no error");
  393. XCTAssertNil([UICKeyChainStore stringForKey:passwordKey service:serviceName error:&error], @"removed password");
  394. XCTAssertNil(error, @"no error");
  395. }
  396.  
  397. - (void)testClassMethodsSetAndRemoveItem
  398. {
  399. // write to keychain
  400. [UICKeyChainStore setString:kStubString forKey:kStubKey];
  401.  
  402. // read from keychain, test keychain contains item
  403. NSString *actualString = [UICKeyChainStore stringForKey:kStubKey];
  404. NSString *expectedString = kStubString;
  405. XCTAssertEqualObjects(expectedString, actualString,
  406. @"expected %@ but got %@", expectedString, actualString);
  407.  
  408. // remove item from keychain
  409. [UICKeyChainStore removeItemForKey:kStubKey];
  410.  
  411. // read from keychain, test keychain doesn't contain item
  412. actualString = [UICKeyChainStore stringForKey:kStubKey];
  413. expectedString = NULL;
  414.  
  415. XCTAssertEqualObjects(expectedString, actualString,
  416. @"expected %@ but got %@", expectedString, actualString);
  417. }
  418.  
  419. - (void)testClassMethodsSetAndRemoveItemWithNoError
  420. {
  421. NSError *error;
  422.  
  423. [UICKeyChainStore setString:kStubString forKey:kStubKey error:&error];
  424. XCTAssertNil(error, @"no error");
  425.  
  426. NSString *actualString = [UICKeyChainStore stringForKey:kStubKey error:&error];
  427. XCTAssertNil(error, @"no error");
  428. NSString *expectedString = kStubString;
  429. XCTAssertEqualObjects(expectedString, actualString,
  430. @"expected %@ but got %@", expectedString, actualString);
  431.  
  432. // remove item from keychain
  433. [UICKeyChainStore removeItemForKey:kStubKey error:&error];
  434. XCTAssertNil(error, @"no error");
  435.  
  436. // read from keychain, test keychain doesn't contain item
  437. actualString = [UICKeyChainStore stringForKey:kStubKey error:&error];
  438. XCTAssertNil(error, @"no error");
  439. expectedString = NULL;
  440.  
  441. XCTAssertEqualObjects(expectedString, actualString,
  442. @"expected %@ but got %@", expectedString, actualString);
  443. }
  444.  
  445. - (void)testInstanceMethodsSetAndRemoveItem
  446. {
  447. // create an instance
  448. UICKeyChainStore *store = [UICKeyChainStore keyChainStoreWithService:kStubService];
  449. // write to keychain
  450. [store setString:kStubString forKey:kStubKey];
  451. [store synchronize];
  452.  
  453. // read from keychain, test keychain contains item
  454. NSString *actualString = [store stringForKey:kStubKey];
  455. NSString *expectedString = kStubString;
  456. XCTAssertEqualObjects(expectedString, actualString,
  457. @"expected %@ but got %@", expectedString, actualString);
  458.  
  459. // remove item from keychain
  460. [store removeItemForKey:kStubKey];
  461. [store synchronize];
  462.  
  463. // read from keychain, test keychain doesn't contain item
  464. actualString = [store stringForKey:kStubKey];
  465. expectedString = NULL;
  466. XCTAssertEqualObjects(expectedString, actualString,
  467. @"expected %@ but got %@", expectedString, actualString);
  468.  
  469. actualString = [store description];
  470. expectedString = @"(\n)";
  471. XCTAssertEqualObjects(expectedString, actualString,
  472. @"expected %@ but got %@", expectedString, actualString);
  473. }
  474.  
  475. - (void)testInstanceMethodsSetAndRemoveItemWithNoError
  476. {
  477. NSError *error;
  478.  
  479. UICKeyChainStore *store = [UICKeyChainStore keyChainStoreWithService:kStubService];
  480.  
  481. [store setString:kStubString forKey:kStubKey error:&error];
  482. XCTAssertNil(error, @"no error");
  483. [store synchronizeWithError:&error];
  484. XCTAssertNil(error, @"no error");
  485.  
  486. NSString *actualString = [store stringForKey:kStubKey error:&error];
  487. XCTAssertNil(error, @"no error");
  488. NSString *expectedString = kStubString;
  489. XCTAssertEqualObjects(expectedString, actualString,
  490. @"expected %@ but got %@", expectedString, actualString);
  491.  
  492. [store removeItemForKey:kStubKey error:&error];
  493. XCTAssertNil(error, @"no error");
  494. [store synchronizeWithError:&error];
  495. XCTAssertNil(error, @"no error");
  496.  
  497. actualString = [store stringForKey:kStubKey error:&error];
  498. XCTAssertNil(error, @"no error");
  499. expectedString = NULL;
  500. XCTAssertEqualObjects(expectedString, actualString,
  501. @"expected %@ but got %@", expectedString, actualString);
  502.  
  503. actualString = [store description];
  504. expectedString = @"(\n)";
  505. XCTAssertEqualObjects(expectedString, actualString,
  506. @"expected %@ but got %@", expectedString, actualString);
  507. }
  508.  
  509. - (void)testInstanceMethodsSetAndRemoveWithNilValue
  510. {
  511. UICKeyChainStore *store = [UICKeyChainStore keyChainStoreWithService:kStubService];
  512.  
  513. [store setString:kStubString forKey:kStubKey];
  514. [store synchronize];
  515.  
  516. NSString *actualString = [store stringForKey:kStubKey];
  517. NSString *expectedString = kStubString;
  518. XCTAssertEqualObjects(expectedString, actualString,
  519. @"expected %@ but got %@", expectedString, actualString);
  520.  
  521. [store setString:nil forKey:kStubKey];
  522. [store synchronize];
  523.  
  524. actualString = [store stringForKey:kStubKey];
  525. expectedString = NULL;
  526. XCTAssertEqualObjects(expectedString, actualString,
  527. @"expected %@ but got %@", expectedString, actualString);
  528.  
  529. actualString = [store description];
  530. expectedString = @"(\n)";
  531. XCTAssertEqualObjects(expectedString, actualString,
  532. @"expected %@ but got %@", expectedString, actualString);
  533. }
  534.  
  535. - (void)testObjectSubscripting
  536. {
  537. // create an instance
  538. UICKeyChainStore *store = [UICKeyChainStore keyChainStoreWithService:kStubService];
  539.  
  540. // write to keychain using obj subscripting
  541. store[kStubKey] = kStubString;
  542. [store synchronize];
  543.  
  544. NSString *actualString = store[kStubKey];
  545. NSString *expectedString = kStubString;
  546.  
  547. // read from keychain using obj subscripting
  548. XCTAssertEqualObjects(expectedString, actualString, @"expected %@ but got %@", expectedString, actualString);
  549.  
  550. store[kStubKey] = nil;
  551. [store synchronize];
  552.  
  553. actualString = store[kStubKey];
  554. expectedString = NULL;
  555.  
  556. XCTAssertEqualObjects(expectedString, actualString, @"expected %@ but got %@", expectedString, actualString);
  557. }
  558.  
  559. @end

3: 其他一参考版本

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

注意使用 keychain 要导入 Security.framework

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

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

    iOS的keychain服务提供了一种安全的保存私密信息(密码,序列号,证书等)的方式,每个ios程序都有一个独立的keychain存储.相对于 NSUserDefaults.文件保存等一般方式,ke ...

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

    1.传统的保存用户名,密码方式 SharedPreferences Editor editor = shareReference.edit(); editor.putString(KEY_NAME,& ...

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

    之前在Android简易实战教程--第七话<在内存中存储用户名和密码> 那里是把用户名和密码保存到了内存中,这一篇把用户名和密码保存至SharedPreferences文件.为了引起误导, ...

  4. git保存用户名和密码

    git保存用户名和密码 简介:tortoiseGit(乌龟git)图形化了git,我们用起来很方便,但是我们拉取私有项目的时候,每次都要输入用户名和密码很麻烦,这里向大家介绍怎么避免多少输入 试验环境 ...

  5. 终于解决“Git Windows客户端保存用户名与密码”的问题(转载)

    add by zhj:不建议用这种方法,建议用SSH,参见 TortoiseGit密钥的配置 http://www.cnblogs.com/ajianbeyourself/p/3817364.html ...

  6. Git Windows客户端保存用户名和密码

    解决Git Windows客户端保存用户名和密码的方法,至于为什么,就不想说了. 1. 添加一个HOME环境变量,值为%USERPROFILE% 2. 开始菜单中,点击“运行”,输入“%Home%”并 ...

  7. TortoiseGit+msysgit保存用户名和密码

    本文以windows系统为例 保存用户名和密码 在C盘的c:\Users**qing** (或可能是C:\Users\Administrator) (替换自己的用户名)找到.gitconfig, 如果 ...

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

    使用Keychain存储用户敏感信息 iOS的keychain服务提供了一种安全的保存私密信息(密码,序列号,证书等)的方式,每个ios程序都有一个独立的keychain存储.相对于 NSUserDe ...

  9. Git Windows客户端保存用户名与密码

    1. 在Windows中添加一个HOME环境变量,值为%USERPROFILE%,如下图: 2. 在“开始>运行”中打开%Home%,新建一个名为“_netrc”的文件. 3. 用记事本打开_n ...

随机推荐

  1. Android中XML解析

    package com.example.thebroadproject; public class Book { private int id; private String name; privat ...

  2. wpfのpack协议

    当引用的资源需要做成dll时,要用此协议 协议:pack://      授权:有两种.一种用于访问编译时已经知道的文件,用application:///.一种用于访问编译时不知道.运行时才知道的文件 ...

  3. WDCP控制面板如何安装PDO_mysql组件

    http://osacar.iteye.com/blog/2098431 执行wget -c http://down.wdlinux.cn/in/pdo_mysql_ins.sh再执行chmod 75 ...

  4. centos6.6 设置静态网络

    [root@localhost ~]# vi /etc/sysconfig/network-scripts/ifcfg-eth0 DEVICE=eth0HWADDR=08:00:27:3D:5F:38 ...

  5. 如何用linux远程登录windows计算机

    大家可能试过用windows远程登录另一个windows pc机,今天大家将会学到如何用 linux远程登录你的windows系统. 首先大家要做到得救是将自己linux和windows操作机的IP地 ...

  6. 真正意义上下一代 Windows Embedded:有关 Windows 10 "Athens" 的事

    早在去年 BUILD 大会上,Joe Belfiore 就在一台巨大的 "脚踩钢琴" 上简短展示过 "Windows on Device"(又名 Windows ...

  7. 【leetcode❤python】237. Delete Node in a Linked List

    #-*- coding: UTF-8 -*- # Definition for singly-linked list.# class ListNode(object):#     def __init ...

  8. HDU 5046 Airport(dlx)

    题目链接:http://acm.hdu.edu.cn/showproblem.php?pid=5046 题意:n个城市修建m个机场,使得每个城市到最近进场的最大值最小. 思路:二分+dlx搜索判定. ...

  9. 一个关于echo的小知识点

    一个关于echo的小知识点     echo一个布尔值时,如果是true,输出1,而如果是false,将什么都不输出! 网上搜的一个解释: 对于数字类型来说,false 确实 是 0, 而对strin ...

  10. PowerShell 4 on win7 sp1

    https://www.microsoft.com/en-hk/download/details.aspx?id=40855 文件太多了,按照这个http://stackoverflow.com/qu ...