SFAuthorizationPluginView пример NameAndPassword зависает после нажатия кнопки
Я использую исправленную версию NameAndPassword, как здесь: https://github.com/skycocker/NameAndPassword
При использовании этого за пределами окна входа в систему (например, system.login.screensaver или моего собственного права на тестирование) с использованием только плагина NameAndPassword окно зависает примерно на 10 секунд после нажатия кнопки "ОК" или "Отмена".
Добавляя некоторые журналы, я вижу, что MechanismDestroy вызывается для плагина и NameAndPassword освобождается, но он никогда не попадает в dealloc в NameAndPassword. Я также не вижу, чтобы PluginDestroy вызывали. SecurityAgent зависает еще 10 секунд после вызова MechanismDestroy.
Я видел этот связанный пост: SecurityAgentPlugin больше не работает на Yosemite (SFAuthorizationPluginView)
Но следование принятому ответу не работает, и в соответствии со Справочником по плагину авторизации не нужно вызывать didDeactivate (нет вызовов RequestInterrupt и никогда не вызывается MechanismDeactivate). Вызов SetResult должен быть достаточным.
Я могу взломать его, вытащив окно из окна просмотра и принудительно закрыв его, но должен быть способ заставить его работать как задумано.
1 ответ
Если мой ответ никому не поможет, значит, у меня была та же проблема, и я нашел другой способ (не чистый, даже довольно грязный), потому что я не мог заставить предложенные решения работать. Я уничтожаю окно, если идентификаторы действительны (тестирую их). Таким образом, если идентификаторы недействительны, окно все еще существует.
- (void)buttonPressed:(SFButtonType)inButtonType
{
NSString *userNameString;
NSString *passwordString;
userNameString = mUserName;
passwordString = [mPPasswordSecureTextField stringValue];
// if the OK button was pressed, write the identity and credentials and allow authorization,
// otherwise, if the cancel button was pressed, cancel the authorization
if (inButtonType == SFButtonTypeOK)
{
const char *puserName = [userNameString UTF8String];
const char *ppassword = [passwordString UTF8String];
AuthorizationValue userNameValue = { strlen(puserName) + 1, (char*)puserName };
AuthorizationValue userPasswordValue = { strlen(ppassword) + 1, (char*)ppassword };
// add the username and password to the context values
[self callbacks]->SetContextValue([self engineRef], kAuthorizationEnvironmentUsername, 1, &userNameValue);
[self callbacks]->SetContextValue([self engineRef], kAuthorizationEnvironmentPassword, 1, &userPasswordValue);
// allow authorization
[self callbacks]->SetResult([self engineRef], kAuthorizationResultAllow);
// to know if we must close the window
// try to auth with the provided user and pswd
BOOL status = [self macosTestLogin: puserName with: ppassword];
if(status == YES)
{
// the user and pwd are good, we can close the window
NSView* v;
// if we are in sleep, screensaver and lock mode (don't work in loggin mode,
// but don't be sad loggin mode have a workaround in config authdb,
// the setting is shared true)
if (mUseIPView) {
v = mPasswordView;
NSWindow* w = [v window];
[w close];
}
}
// suggested workaround (don't work)
[self didDeactivate];
}
else if (inButtonType == SFButtonTypeCancel)
{
// cancel authorization
[self callbacks]->SetResult([self engineRef], kAuthorizationResultUserCanceled);
}
}
И тестовая функция:
- (BOOL) macosTestLogin: (const char *)userName with: (const char *)password
{
// hack to know if we must close the window
// try to auth with the provided user and pswd
AuthorizationRef authorization = NULL;
AuthorizationItem items[2];
items[0].name = kAuthorizationEnvironmentPassword;
items[0].value = (char*) password;
items[0].valueLength = strlen(password);
items[0].flags = 0;
items[1].name = kAuthorizationEnvironmentUsername;
items[1].value = (char*) userName;
items[1].valueLength = strlen(userName);
items[1].flags = 0;
AuthorizationRights rights = {2, items};
AuthorizationEnvironment enviroment = {2, items};
// creates a new authorization reference and provides an option to authorize or preauthorize rights.
AuthorizationCreate(NULL, &enviroment, kAuthorizationFlagDefaults, &authorization);
AuthorizationFlags flag = kAuthorizationFlagDefaults| kAuthorizationFlagExtendRights;
OSStatus status = AuthorizationCopyRights(authorization, &rights, &enviroment, flag, NULL);
if(status == errAuthorizationSuccess)
{
return YES;
}
return NO;
}
Это работает для меня, я делаю это только в режиме "заставки", при входе в систему достаточно опции shared = true.
Я нашел другой взлом - я получил счетчик ссылок экземпляра механизма аутентификации и выпустил все, кроме последнего. Сделайте это после вызова setResult. Это решает проблему. Так не должно быть - но Apple не дает нам большого выбора.