私のインストールでは、ユーザーは Shibboleth [1] でログインしますが、「ユーザーがログインしました」イベントで実行されるように設定したルール [2] は実行されません。
一方、通常の Drupal の方法で管理者としてログインすると、ルールが実行されます。
これは、外部ログイン イベントがまったく処理されないということですか?
これを克服する方法はありますか?
私のインストールでは、ユーザーは Shibboleth [1] でログインしますが、「ユーザーがログインしました」イベントで実行されるように設定したルール [2] は実行されません。
一方、通常の Drupal の方法で管理者としてログインすると、ルールが実行されます。
これは、外部ログイン イベントがまったく処理されないということですか?
これを克服する方法はありますか?
これは 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());
}
}
[...]
注:テストされていないコードです。タイプミスやその他のばかげた見落としに注意してください ;)
これを行う場合は、上記のリンク先のバグ レポートにパッチとして送信することをお勧めします。(明らかに動作する場合のみ;)
Drupal は実行hooks
されます。つまり、モジュールはコードの一部を実行する機会を得ます。たとえば、ログイン時に hook_user が呼び出されます。
多くの場合、モジュールはdrupal_goto()
そのようなフック内で a を呼び出します。これは激しく壊れます。Drupal_goto はすべてを強制終了し、リダイレクト ヘッダーを送信してから、アプリケーションを終了します。他のフックは実行されません。
devel モジュールをインストールし、「リダイレクトを表示」の設定を切り替えることで、「不正な」goto を見つけることができます。
このような場合、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」は、認証モジュールよりも大きい任意の数値です。