【问题标题】:SFAuthorizationPluginView example NameAndPassword hangs after button is pressedSFAuthorizationPluginView 示例 NameAndPassword 在按下按钮后挂起
【发布时间】:2016-10-04 13:21:32
【问题描述】:

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

在登录窗口外使用此功能(例如 system.login.screensaver 或我自己的测试权限),仅使用 NameAndPassword 插件时,按确定或取消后窗口会挂起约 10 秒。

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

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

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

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

【问题讨论】:

    标签: objective-c macos authorization osx-elcapitan sfauthorizationpluginview


    【解决方案1】:

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

    【讨论】:

      【解决方案2】:

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

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

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 2013-08-13
        • 1970-01-01
        • 1970-01-01
        • 2017-08-27
        • 2013-08-25
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        相关资源
        最近更新 更多