规则模块没有获取(外部)“用户登录”事件?

时间:2010-10-20 09:57:37

标签: drupal shibboleth drupal-rules

在我的安装中,用户使用Shibboleth [1]登录,但是我设置为在“用户已登录”事件中执行的规则[2]未执行。

另一方面,当我以管理员身份以正常的Drupal方式登录时,规则就会执行。

这是否意味着根本不处理外部登录事件?

有没有办法克服这个问题?

[1] http://drupal.org/project/shib_auth

[2] http://drupal.org/project/rules

3 个答案:

答案 0 :(得分:1)

这似乎是a bug of the Shibboleth module,因此登录'event'确实没有被它引发(在Drupal术语中,它不会使用hook_user()调用$op = 'login')。

Looking at the Shibboleth code,登录似乎发生在hook_init()实施中:

/**
* Create a new user based on informations from the Shibboleth handler if it's necessary or log in.
*/
function shib_auth_init() {
  global $user;

  $unameVar = variable_get('shib_auth_username_variable', 'REMOTE_USER');
  $umailVar = variable_get('shib_auth_username_email', 'HTTP_SHIB_MAIL');

  // If
  // - The user isn't logged in
  // - There is Shibboleth authentication in the background
  // - The settings are fine and there has been a valid username setted up
  // - The settings are fine and there has been a valid user email address setted up
  if (!$user->uid && $_SERVER['HTTP_SHIB_IDENTITY_PROVIDER']) {
    if ($_SERVER[$unameVar] && $_SERVER[$umailVar]) {
      user_external_login_register($_SERVER[$unameVar], "shib_auth");
    }
    else {
      drupal_set_message(t("Username or e-mail address is missing. Maybe the Shibboleth configuration is not perfect."),"error");
    }
  }
  if ($user->uid && $_SERVER['HTTP_SHIB_IDENTITY_PROVIDER']) {
    $account = user_save($user,array('mail' => $_SERVER[$umailVar]));
    // Terminate if an error occured during user_save().
    if (!$account) {
      drupal_set_message(t("Error saving user account."), 'error');
      return;
    }
    $user = $account;
  }
} // function shib_auth_init()

因此,您需要修补此问题,并确保调用user_module_invoke()。执行此操作的标准方法是在成功登录后调用user_authenticate_finalize()(然后将调用user_module_invoke()),因此您需要在user_external_login_register()调用后添加:

    [...]
    if ($_SERVER[$unameVar] && $_SERVER[$umailVar]) {
      user_external_login_register($_SERVER[$unameVar], "shib_auth");
      // Do we have a logged in user now?
      if ($user->uid) {
        // Yes, ensure watchdog logging and proper invocation of hook_user
        // NOTE: We pass an empty array, as no form submit was involved here,
        // but we could also pass an array with 'unameVar' and 'umailVar',
        // as they would be the closest substitute.
        user_authenticate_finalize(array());
      }
    }
    [...]

注意:未经测试的代码,谨防拼写错误和其他愚蠢的疏忽;)

如果您最终这样做,您可能希望将其作为补丁提交到上面链接的错误报告中。 (只有当它有效时,显然;)

答案 1 :(得分:0)

在这些情况下,Drupal加载模块的顺序非常重要。您需要设置规则,以便在验证模块之后加载规则。例如,使用ldap_integration

mysql> UPDATE system SET weight=20 WHERE name="rules";
mysql> UPDATE system SET weight=20 WHERE name="rules_forms";
mysql> UPDATE system SET weight=0 WHERE name="ldapauth";

“20”是一个任意数字,大于您的身份验证模块。

答案 2 :(得分:0)

Drupal运行hooks,意味着模块有机会运行一段代码。例如。在登录时调用hook_user。

很多时候,模块会在这样的钩子中调用drupal_goto()。这将严重打破。 Drupal_goto会杀死所有内容,发送一个redirect-header,然后死掉应用程序。没有其他钩子会被运行。

  1. Hooks永远不应该调用drupal_goto(),die()或其他类似的破坏性函数。但是,由于没有任何东西可以阻止人们违反这一规则,人们(模块)会破坏它。
  2. 由于同样的原因,
  3. form_alter永远不应该调用goto,die等等。
  4. 你可以通过安装devel模块并切换设置“show redirects”来找到任何“非法”goto,你会看到,例如, sibbletooth调用了一个不应该有的重定向。