4

我正在使用 NameAndPassword 的修补版本,如下所示:https ://github.com/skycocker/NameAndPassword

当在登录窗口之外使用这个(例如 system.login.screensaver 或我自己的测试权限)时,仅使用 NameAndPassword 插件,在按下 Ok 或取消后,窗口会挂起大约 10 秒。

添加一些日志,我看到插件上调用了 MechanismDestroy 并且 NameAndPassword 被释放,但它永远不会在 NameAndPassword 中释放。我也没有看到 PluginDestroy 被调用。在调用 MechanismDestroy 后,SecurityAgent 会再挂起 10 秒。

我看到了这个相关的帖子:SecurityAgentPlugin not working on Yosemite (SFAuthorizationPluginView)

但是遵循接受的答案不起作用,并且根据授权插件参考 didDeactivate 不需要被调用(没有调用 RequestInterrupt 和 MechanismDeactivate 永远不会被调用)。调用 SetResult 应该就足够了。

我可以通过从视图中获取窗口并强行关闭它来破解它,但必须有一种方法让它按预期工作。

4

2 回答 2

0

我发现了不同的 hack - 我得到了 auth-mechanism 实例的引用计数并释放了除最后一个之外的所有实例。在 setResult 调用之后执行此操作。这解决了这个问题。它不应该是这样的——但苹果并没有给我们太多选择。

于 2017-03-21T15:03:00.670 回答
0

如果我的回复不能帮助某人,我遇到了同样的问题并找到了不同的方法(不干净,甚至很脏),因为我无法使建议的解决方案发挥作用。如果标识符有效,我会销毁窗口(我测试它们)。像这样,如果标识符无效,窗口仍然存在。

- (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 就足够了。

于 2019-12-05T13:24:14.547 回答