Модуль правил не улавливает (внешнее) событие входа пользователя?

В моей установке пользователи входят в систему с помощью Shibboleth [1], но правило [2], которое я настроил для выполнения при событии «Пользователь вошел в систему», не выполняется.

С другой стороны, когда я вхожу в систему как администратор обычным способом Drupal, правило выполняется.

Означает ли это, что событие внешнего входа вообще не обрабатывается?

Есть ли способ преодолеть это?

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

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


person Kay Pale    schedule 20.10.2010    source источник


Ответы (3)


Похоже, это ошибка модуля Shibboleth, так что "событие" входа действительно не вызывается им (в терминах Drupal он не вызывает hook_user() с $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());
      }
    }
    [...]

ПРИМЕЧАНИЕ. Непроверенный код, остерегайтесь опечаток и других глупых оплошностей ;)

Если вы в конечном итоге сделаете это, вы можете отправить его в качестве исправления к отчету об ошибке, указанному выше. (только если это работает, очевидно;)

person Henrik Opel    schedule 20.10.2010

В этих случаях очень важен порядок, в котором 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» — это произвольное число, которое больше, чем ваш модуль аутентификации.

person Andrew Sledge    schedule 20.10.2010
comment
ИМХО, порядок выполнения (или загрузки) здесь не имеет значения, так как хук вообще не вызывается! (Порядок будет актуален только в том случае, если он захочет отреагировать после реализации того же хука другим модулем, но в этом случае в первую очередь не на что реагировать) - person Henrik Opel; 21.10.2010

Drupal запускает hooks, то есть модули получают возможность запускать часть кода. Например. при входе в систему вызывается hook_user.

Слишком часто модули вызывают drupal_goto() внутри таких хуков. Это сильно сломает. Drupal_goto убьет все, отправит заголовок перенаправления, а затем умрет приложение. Никакие другие хуки запускаться не будут.

  1. Хуки никогда не должны вызывать drupal_goto(), die() или другие подобные деструктивные функции. Но поскольку ничто не удерживает людей от нарушения этого правила, люди (модули) его нарушат.
  2. form_alter никогда не должен вызывать goto, dies и т. д. по той же причине.

Вы можете найти любые «незаконные» переходы, установив модуль devel и переключив настройку «показывать перенаправления», вы увидите, если, например. sibbletooth вызвал перенаправление там, где его быть не должно.

person berkes    schedule 21.10.2010