ページ

2010年3月25日木曜日

Keychain Services 調査 (20) 認証フロー(REST向け)Keychain item 更新

このエントリーをブックマークに追加 このエントリーを含むはてなブックマーク

(前回)Cocoaの日々: Keychain Services 調査 (19) 認証フロー(REST向け)実装開始

以前から Keychain item の作成とパスワードの取得は実装していたが、更新はまだだった。今回更新処理を実装する。

更新には SecKeychainItemModifyAttributesAndData を使う。
Mac Dev Center: Keychain Services Reference - SecKeychainItemModifyAttributesAndData

-[AccountManager storeLoginAccount:] にこの関数を使った更新処理を加える。

- (BOOL)storeLoginAccount:(LoginAccount*)loginAccount
{
OSStatus status;
SecKeychainItemRef itemRef = nil;
BOOL result = NO;

const char *serviceNameUTF8 = [loginAccount.serviceName UTF8String];
const char *loginIdUTF8 = [loginAccount.loginId UTF8String];
const char *passwordUTF8 = [loginAccount.password UTF8String];

status = SecKeychainFindGenericPassword(NULL,
strlen(serviceNameUTF8),
serviceNameUTF8,
strlen(loginIdUTF8),
loginIdUTF8,
NULL,
NULL,
&itemRef);
if (status == errSecItemNotFound) {
status = SecKeychainAddGenericPassword(NULL,
   strlen(serviceNameUTF8),
   serviceNameUTF8,
   strlen(loginIdUTF8),
   loginIdUTF8,
   strlen(passwordUTF8),
   passwordUTF8,
   NULL);
if (status == errSecSuccess) {
NSLog(@"created keychain item");
result = YES;
} else {
NSLog(@"ERROR:SecKeychainAddGenericPassword:%d", status);
result = NO;
}

} else {
status = SecKeychainItemModifyAttributesAndData(itemRef,
NULL,
strlen(passwordUTF8),
passwordUTF8);
if (status == errSecSuccess) {
NSLog(@"updated keychain item");
result = YES;
} else {
NSLog(@"ERROR:SecKeychainItemModifyAttributesAndData:%d", status);
result = NO;
}
}
if (itemRef) {
CFRelease(itemRef);
}

return result;
}


最初に keychain を検索し、無ければ SecKeychainAddGenericPassword で新規作成する。存在する場合は SecKeychainItemModifyAttributesAndData を使い更新する。


ソースは GitHub からどうぞ。
KeychainSample2 at 2010-03-25 from xcatsan's SampleCode - GitHub


なお、前回 NSTextField にバインディングされたメンバ変数の同期が遅れていた件は、Bindings設定で "Continuously Updates Value" を設定することで解決した。


- - - -
次回こそは Twitpic にとりかかりたい。