2

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

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

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

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

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

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

4

3 回答 3

1

这似乎是Shibboleth 模块的错误,因此登录“事件”确实不是由它引发的(在 Drupal 术语中,它不会调用hook_user()with $op = 'login')。

查看 Shibboleth 代码,登录似乎发生在其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());
      }
    }
    [...]

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

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

于 2010-10-20T20:48:19.927 回答
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”是一个任意数字,大于您的身份验证模块。

于 2010-10-20T11:21:45.047 回答
0

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

很多时候,模块会drupal_goto()在这样的钩子内部调用。这将严重破坏。Drupal_goto 将杀死一切,发送重定向标头,然后终止应用程序。不会运行其他挂钩。

  1. 钩子永远不应该调用 drupal_goto()、die() 或其他此类破坏性函数。但既然没有什么能阻止人们打破这条规则,人们(模块)就会打破它。
  2. 出于同样的原因,form_alter 永远不应该调用 goto、dies 等等。

您可以通过安装 devel 模块并切换设置“显示重定向”来找到任何“非法”的 goto,您将看到例如 sibbletooth 是否在它不应该有的地方调用了重定向。

于 2010-10-21T10:19:43.980 回答