Objective c 创建类型为'的钥匙链项目;网络表单密码';在MacOSX上

Objective c 创建类型为'的钥匙链项目;网络表单密码';在MacOSX上,objective-c,macos,keychain,Objective C,Macos,Keychain,我正在开发一个应用程序,当用户选择一个菜单项时,他们会被带到一个网页。该网页需要身份验证,为了方便用户,我想将他们的身份验证信息传递给存储在我的应用程序中的Safari/Firefox/Chrome 我尝试过创建通用的和互联网的钥匙链项目,它们在钥匙链访问中显示得很漂亮,但没有网络浏览器会注意到它们 我注意到,为浏览器存储的钥匙链项目的类型为“Web表单密码” 当我尝试创建类型为“kSecAuthenticationTypeHTMLForm”的钥匙链项目时,它在钥匙链访问中显示为“interne

我正在开发一个应用程序,当用户选择一个菜单项时,他们会被带到一个网页。该网页需要身份验证,为了方便用户,我想将他们的身份验证信息传递给存储在我的应用程序中的Safari/Firefox/Chrome

我尝试过创建通用的和互联网的钥匙链项目,它们在钥匙链访问中显示得很漂亮,但没有网络浏览器会注意到它们

我注意到,为浏览器存储的钥匙链项目的类型为“Web表单密码”

当我尝试创建类型为“kSecAuthenticationTypeHTMLForm”的钥匙链项目时,它在钥匙链访问中显示为“internet密码”。我修改了EMKeychain类中的一些代码:

+ (EMInternetKeychainItem *)addInternetKeychainItemForServer:(NSString *)server
                                            withUsername:(NSString *)username
                                                password:(NSString *)password
                                                    path:(NSString *)path
                                                    port:(NSInteger)port
                                                protocol:(SecProtocolType)protocol
{
if (!username || !server || !password)
    return nil;

const char *serverCString = [server UTF8String];
const char *usernameCString = [username UTF8String];
const char *passwordCString = [password UTF8String];
const char *pathCString = [path UTF8String];

if (!path || [path length] == 0)
    pathCString = "";

SecKeychainItemRef item = nil;
OSStatus returnStatus = SecKeychainAddInternetPassword(NULL, strlen(serverCString), serverCString, 0, NULL, strlen(usernameCString), usernameCString, strlen(pathCString), pathCString, port, protocol, kSecAuthenticationTypeHTMLForm, strlen(passwordCString), (void *)passwordCString, &item);

if (returnStatus != noErr || !item)
{
    if (_logsErrors)
        NSLog(@"Error (%@) - %s", NSStringFromSelector(_cmd), GetMacOSStatusErrorString(returnStatus));
    return nil;
}
return [EMInternetKeychainItem _internetKeychainItemWithCoreKeychainItem:item forServer:server username:username password:password path:path port:port protocol:protocol];
}

最有可能的问题是,密钥链条目是使用ACL创建的,该ACL不允许Safari访问其内容。(我认为Chrome和Firefox使用自己专有的密码数据库而不是钥匙链,因此修改钥匙链不会影响这些浏览器。)

尝试使用
SecKeychainItemSetAccess
允许访问所有应用程序。我使用以下代码创建这样一个许可的SecAccess对象:

// Create an access object.
SecAccessRef access;
status = SecAccessCreate(CFSTR("item description"), 
                         NULL, // Only this app has access (this'll get changed in a moment)
                         &access);
if (status) { ... }

// Override access control to provide full access to all applications.
NSArray *aclList = nil;
status = SecAccessCopyACLList(access, (CFArrayRef *)&aclList);
if (status) { ... }
for (id object in aclList) { // will do just one iteration
    SecACLRef acl = (SecACLRef)object;

    CFArrayRef applist = NULL;
    CFStringRef desc = NULL;
    CSSM_ACL_KEYCHAIN_PROMPT_SELECTOR cakps;

    status = SecACLCopySimpleContents(acl, &applist, &desc, &cakps);
    if (status)  { ... }

    status = SecACLSetSimpleContents(acl, 
                                     NULL, // All applications.
                                     desc,
                                     &cakps);
    if (status) { ... }

    if (applist != NULL)
        CFRelease(applist);
    if (desc != NULL)
        CFRelease(desc);
}

谢谢你的回答!如果我有足够的声誉,我会投票支持它。