规则模块未获取(外部)“用户登录”信息事件?

发布于 2024-09-28 03:04:14 字数 386 浏览 1 评论 0原文

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

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

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

有办法克服这个问题吗?

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

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

In my installation the users login with Shibboleth [1], but the rule [2] I've set up to be executed on "User has logged in" event, isn't executed.

On the other hand, when I login as administrator through the normal Drupal way, the rule is executed.

Does this mean that the external login event isn't handled at all?

Is there a way to overcome this?

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

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

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(3

无力看清 2024-10-05 03:04:14

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

查看 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()< /a> 成功登录后(这将依次调用 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());
      }
    }
    [...]

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

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

This seems to be a bug of the Shibboleth module, so the login 'event' is indeed not raised by it (in Drupal terms, it does not invoke hook_user() with $op = 'login').

Looking at the Shibboleth code, the login seems to happen in its hook_init() implementation:

/**
* 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()

So you'd need to patch this and and ensure that user_module_invoke() is called. The standard way to do this would be to call user_authenticate_finalize() after a successful login (which will in turn call user_module_invoke()), so you'd add that after the user_external_login_register() call:

    [...]
    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());
      }
    }
    [...]

NOTE: Untested code, beware of typos and other stupid oversights ;)

Should you end up doing this, you might want to submit it as a patch to the bug report linked above. (only if it works, obviously ;)

笑看君怀她人 2024-10-05 03:04:14

在这些情况下,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”是一个比您的身份验证模块更大的任意数字。

The order in which Drupal loads the modules is very important in these cases. You will need to set rules so that it is loaded after your authentication module. For instance, with 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" is an arbitrary number that is bigger than whatever your authentication module is.

毁梦 2024-10-05 03:04:14

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

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

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

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

Drupal runs hooks, meaning modules get the chance to run a piece of code. E.g. on login a hook_user is called.

Too often, modules will call a drupal_goto() inside such hooks. This will break severely. Drupal_goto will kill everything, send a redirect-header, then die the application. No other hooks will be ran.

  1. Hooks should never call drupal_goto(), die() or other such destructive functions. But since nothing keeps people from breaking this rule, people (modules) will break it.
  2. form_alter should never invoke goto's, dies and so forth, for the same reason.

You can find any "illegal" goto's by installing devel module and toggling the setting "show redirects", you will see if e.g. sibbletooth invoked a redirect where it should not have.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文