Objective c SecKeychain加载项
我想使用密钥链存储Mac OSX应用程序中的SMTP数据。我阅读了Apple的Keychain Services编程指南,并编写了以下方法来存储数据:Objective c SecKeychain加载项,objective-c,macos,cocoa,keychain,Objective C,Macos,Cocoa,Keychain,我想使用密钥链存储Mac OSX应用程序中的SMTP数据。我阅读了Apple的Keychain Services编程指南,并编写了以下方法来存储数据: - (BOOL)saveSMPTData { OSStatus err; SecKeychainItemRef item = nil; SecProtocolType protocol = kSecProtocolTypeSMTP; const char *accessLabelUTF8 = [KEYCHA
- (BOOL)saveSMPTData
{
OSStatus err;
SecKeychainItemRef item = nil;
SecProtocolType protocol = kSecProtocolTypeSMTP;
const char *accessLabelUTF8 = [KEYCHAIN_NAME UTF8String];
const char *serverNameUTF8 = [self.serverName UTF8String];
const char *usernameUTF8 = [self.username UTF8String];
const char *passwordUTF8 = [self.password UTF8String];
SecAccessRef access = createAccess(KEYCHAIN_NAME);
SecKeychainAttribute attrs[] = {
{ kSecLabelItemAttr, (int)strlen(accessLabelUTF8), (char *)accessLabelUTF8 },
{ kSecAccountItemAttr, (int)strlen(usernameUTF8), (char *)usernameUTF8 },
{ kSecServerItemAttr, (int)strlen(serverNameUTF8), (char *)serverNameUTF8 },
{ kSecProtocolItemAttr, sizeof(SecProtocolType), (SecProtocolType *)&protocol }
};
SecKeychainAttributeList attributes = { sizeof(attrs) / sizeof(attrs[0]), attrs };
err = SecKeychainItemCreateFromContent(kSecInternetPasswordItemClass,
&attributes,
(int)strlen(passwordUTF8),
passwordUTF8,
NULL,
access,
&item);
if (access) CFRelease(access);
if (item) CFRelease(item);
return (err == noErr);
}
SecAccessRef createAccess(NSString *accessLabel)
{
OSStatus err;
SecAccessRef access = nil;
NSArray *trustedApplications = nil;
SecTrustedApplicationRef myself;
err = SecTrustedApplicationCreateFromPath(NULL, &myself);
trustedApplications = [NSArray arrayWithObjects:(__bridge id)myself, nil];
err = SecAccessCreate((__bridge CFStringRef)accessLabel,
(__bridge CFArrayRef)trustedApplications, &access);
if (err) return nil;
return access;
}
当然,我也想加载它们。我的第一次尝试如下所示:
- (BOOL)loadDataFromKeychain
{
uint32_t serverNameLength = 0;
const char *serverName = NULL;
uint32_t usernameLength = 0;
const char *username = NULL;
uint32_t passwordLength = 0;
void **password = NULL;
OSStatus err = SecKeychainFindInternetPassword(NULL,
serverNameLength, serverName,
0, NULL,
usernameLength, username,
0, NULL,
0, 0,
0,
&passwordLength, password,
NULL); // How do I get the ItemRef?
return (err == noErr);
}
但这不起作用,我想我知道为什么不起作用。我不知道如何获取SecKeychainFindInternetPassword方法的SecKeychainItemRef
也许有人能帮我?不要声明
密码avoid**
,而是声明它是void*
并传递&password
作为倒数第二个参数
您可能不需要SecKeychainItemRef来完成您想要完成的任务
顺便问一下,您是否尝试过使用Keychain Access验证项目是否进入了钥匙链?这也适用于serverName
和userName
。(这也是提问者在他或她真的需要时获得项目ref的方式:声明一个变量来保存它,然后传递一个指向该变量的指针。)谢谢你的回答!按照您描述的方式声明密码修复了该问题。但我仍然不知道如何获得项目参考。在创建它之后,我无法将其保存在指针中,因为我在重新启动应用程序时只想读取该项。那么我如何搜索正确的项目呢?@kober:使用SecKeychainFindInternetPassword
并让它将项目返回给您,就像您使用SecKeychainItemCreateFromContent
一样。使用SecKeychainFindInternetPassword
我没有得到正确的项目。我现在使用SecKeychainItemCreatePersistentReference
保存我的itemRef,并使用SecKeychainItemCopyFromPersistentReference
获取它。@kober:问题中的代码搜索没有服务器名称或用户名的项目。如果您希望SecKeychainFindInternetPassword
查找使用它们创建的项目,则需要填写这些内容。