gpt4 book ai didi

macos - 仅使用服务名称获取存储在钥匙串(keychain)中的用户名?或 : Where are you supposed to store the Username?

转载 作者:行者123 更新时间:2023-12-03 16:13:00 26 4
gpt4 key购买 nike

因此 OS X 钥匙串(keychain)包含三部分信息:

  • ServiceName(我的应用的名称)
  • 用户名
  • 密码

我显然总是知道 ServiceName。有没有办法找到该 ServiceName 的任何已保存的用户名? (一旦您知道用户名,找到密码就很容易了。)

我更喜欢使用漂亮的 cocoa wrapper ,例如 EMKeychain去做这个。但 EMKeychain 需要用户名才能获取任何钥匙串(keychain)项目!

+ (EMGenericKeychainItem *)genericKeychainItemForService:(NSString *)serviceNameString withUsername:(NSString *)usernameString;

如果您需要用户名来查找凭据,您如何充分利用钥匙串(keychain)中保存的凭据?最佳实践是将用户名保存在 .plist 文件或其他文件中吗?

最佳答案

SecKeychainFindGenericPassword 仅返回单个钥匙串(keychain)项。要查找特定服务的所有通用密码,您需要在钥匙串(keychain)上运行查询。根据您的目标 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, &attrList, &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,
(id)kCFBooleanTrue, 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框架(插头!)。它不支持构建基于属性的查询,但您可以简单地列出所有密码并过滤掉不需要的密码。

- (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 - 仅使用服务名称获取存储在钥匙串(keychain)中的用户名?或 : Where are you supposed to store the Username?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/8451239/

26 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com