创建类型为“Web 表单密码”的钥匙串项目在 Mac OS X 上

发布于 2024-12-11 04:56:55 字数 1798 浏览 0 评论 0原文

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

我尝试过创建通用和互联网钥匙串项目,这些项目在钥匙串访问中显示得很漂亮,但没有网络浏览器识别它们。

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

当我尝试创建类型为“kSecAuthenticationTypeHTMLForm”的钥匙串项时,它在“钥匙串访问”中显示为“互联网密码”。我修改了 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];
}

I'm working on an application where when a user selects a menu item they are brought to a webpage. The webpage requires authentication, and to make things simpler for the user I would like to pass along their authentication information to Safari/Firefox/Chrome that is stored in my application.

I've tried creating generic and internet keychain items, which show up beautifully in Keychain Access, but no web browsers pick up on them.

I've noticed that the keychain items being stored for the browsers have the type "Web Form Password".

When I try to create a keychain item with the type 'kSecAuthenticationTypeHTMLForm' it shows in Keychain Access as 'internet password'. I've modified some code from the EMKeychain class:

+ (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];
}

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(1

·深蓝 2024-12-18 04:56:55

最可能的问题是,钥匙串条目是使用 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);
}

The most likely problem is that the keychain entry is created with an ACL that does not give access to its contents to Safari. (I think Chrome and Firefox use their own proprietary password databases instead of the keychain, so modifying the keychain won't affect those browsers.)

Try using SecKeychainItemSetAccess to permit access to all applications. I use the following code to create such a permissive SecAccess object:

// 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);
}
~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文