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 не дает нам большого выбора.

Другие вопросы по тегам