> Servicename(我的应用程序的名称)
>用户名
>密码
我显然总是知道Servicename.有没有办法找到该Servicename的任何已保存用户名? (一旦知道用户名,就很容易找到密码.)
我更喜欢使用一个漂亮的Cocoa包装器,如EMKeychain来做到这一点.但EMKeychain要求Username获取任何钥匙串项目!
(EMGenericKeychainItem *)genericKeychainItemForService:(Nsstring *)servicenameString withUsername:(Nsstring *)usernameString;
如果您需要用户名来查找凭据,您希望如何充分利用钥匙串中的保存凭据?将用户名保存在.pList文件中的最佳做法是什么?
解决方法 SecKeychainFindGenericPassword仅返回单个钥匙串项.要查找特定服务的所有通用密码,您需要在钥匙串上运行查询.根据您定位的OS X版本,有多种方法可以执行此 *** 作.如果需要在10.5或更低版本上运行,则需要使用SecKeychainSearchCreateFromAttributes.这是一个相当可怕的API.下面是一个返回将用户名映射到密码的字典的方法的粗略剪辑.
- (NSDictionary *)genericPasswordsWithService:(Nsstring *)service { Osstatus status; // Construct a query. const char *utf8Service = [service UTF8String]; SecKeychainAttribute attr = { .tag = kSecServiceItemAttr,.length = strlen(utf8Service),.data = (voID *)utf8Service }; SecKeychainAttribute attrList = { .count = 1,.attr = &attr }; SecKeychainSearchref *search = NulL; status = SecKeychainSearchCreateFromAttributes(NulL,kSecGenericPasswordItemClass,&attrList,&search); if (status) { report(status); return nil; } // Enumerate results. NSMutableDictionary *result = [NSMutableDictionary dictionary]; while (1) { SecKeychainItemRef item = NulL; status = SecKeychainSearchcopyNext(search,&item); if (status) break; // Find 'account' attribute and password value. UInt32 tag = kSecAccountItemAttr; UInt32 format = CSSM_DB_ATTRIBUTE_FORMAT_STRING; SecKeychainAttributeInfo info = { .count = 1,.tag = &tag,.format = &format }; SecKeychainAttributeList *attrList = NulL; UInt32 length = 0; voID *data = NulL; status = SecKeychainItemcopyAttributesAndData(item,&info,NulL,&length,&data); if (status) { CFRelease(item); continue; } NSAssert(attrList->count == 1 && attrList->attr[0].tag == kSecAccountItemAttr,@"SecKeychainItemcopyAttributesAndData is messing with us"); Nsstring *account = [[[Nsstring alloc] initWithBytes:attrList->attr[0].data length:attrList->attr[0].length enCoding:NSUTF8StringEnCoding] autorelease]; Nsstring *password = [[[Nsstring alloc] initWithBytes:data length:length enCoding:NSUTF8StringEnCoding] autorelease]; [result setobject:password forKey:account]; SecKeychainItemFreeAttributesAndData(attrList,data); CFRelease(item); } CFRelease(search); return result;}
对于10.6及更高版本,您可以使用稍微不那么不方便的SecItemcopyMatching API:
- (NSDictionary *)genericPasswordsWithService:(Nsstring *)service { NSDictionary *query = [NSDictionary dictionaryWithObjectsAndKeys: kSecclassGenericPassword,kSecclass,(ID)kcfBooleanTrue,kSecReturnData,kSecReturnAttributes,kSecMatchlimitAll,kSecMatchlimit,service,kSecAttrService,nil]; NSArray *itemDicts = nil; Osstatus status = SecItemcopyMatching((CFDictionaryRef)q,(CFTypeRef *)&itemDicts); if (status) { report(status); return nil; } NSMutableDictionary *result = [NSMutableDictionary dictionary]; for (NSDictionary *itemDict in itemDicts) { NSData *data = [itemDict objectForKey:kSecValueData]; Nsstring *password = [[[Nsstring alloc] initWithData:data enCoding:NSUTF8StringEnCoding] autorelease]; Nsstring *account = [itemDict objectForKey:kSecAttrAccount]; [result setobject:password forKey:account]; } [itemDicts release]; return result;}
对于10.7或更高版本,您可以使用我精彩的LKKeychain框架(PLUG!).它不支持构建基于属性的查询,但您只需列出所有密码并过滤掉您不需要的密码.
- (NSDictionary *)genericPasswordsWithService:(Nsstring *)service { LKKCKeychain *keychain = [LKKCKeychain defaultKeychain]; NSMutableDictionary *result = [NSMutableDictionary dictionary]; for (LKKCGenericPassword *item in [keychain genericPasswords]) { if ([service isEqualToString:item.service]) { [result setobject:item.password forKey:item.account]; } } return result;}
(我没有尝试运行,甚至没有编译上面的任何代码示例;抱歉任何错别字.)
总结以上是内存溢出为你收集整理的macos – 仅使用ServiceName获取存储在Keychain中的用户名?或者:你应该在哪里存储用户名?全部内容,希望文章能够帮你解决macos – 仅使用ServiceName获取存储在Keychain中的用户名?或者:你应该在哪里存储用户名?所遇到的程序开发问题。
如果觉得内存溢出网站内容还不错,欢迎将内存溢出网站推荐给程序员好友。
欢迎分享,转载请注明来源:内存溢出
评论列表(0条)