2011-10-20 15 views
4

私はユーザーがウェブページに持ち込まれたメニュー項目を選択するアプリケーションで作業しています。 Webページには認証が必要で、ユーザーのために認証情報を私のアプリケーションに保存されているSafari/Firefox/Chromeに渡したいと思っているユーザーの方が簡単になります。Mac OS Xで 'Web Form Password'タイプのキーチェーンアイテムを作成する

私は、キーチェーンアクセスに美しく表示される一般的なインターネットキーチェーンアイテムを作成しようとしましたが、ウェブブラウザではそれを認識しません。

ブラウザ用に保存されているキーチェーンアイテムのタイプが「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]; 
} 

答えて

9

最も可能性の高い問題は、キーチェーンエントリがサファリにその内容へのアクセスを与えないACLを使用して作成されていることです。 (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); 
} 
+0

ありがとうございました!私が十分な評判を持っていれば、私はそれを投票するだろう。 – joshbillions