我正在使用Moodle的外部数据库插件,遇到了一个非常烦人的问题。下面是一个示例:
用户名:johndoe@gmail.com 使用他的密码登录,两者都保存在外部数据库中。Moodle获取该数据(用户名,密码)并将其保存在本地(mysql)以及该用户的外部数据库ID中。请记住,外部数据库是发生一切的主要数据库,Moodle仅适用于需要进行测试的授权用户。所以在Moodle中,我有:
用户名: johndoe@gmail.com密码:布拉布拉用户 ID:1234
它工作得很好,除了当 johndoe@gmail.com 决定在外部数据库上更新他的用户名/电子邮件时,所以他希望现在 johndoe@hotmail.com 它。当他尝试登录时,它会登录正常,因为 Moodle 会向外部数据库检查用户名/密码。问题:在 Moodle 中为具有相同密码和用户标识的 johndoe@hotmail.com 创建一个新记录。
我的问题是:如果 userid 已经存在并且不创建新记录,我可以在哪里安全地检查本地数据库?我不想更新 moodlelib 文档,因为我不想将来遇到升级问题。我可以更新外部数据库插件,但无法弄清楚哪里最好。
这是某人做的解决方法 - https://moodle.org/mod/forum/discuss.php?d=232163 - 但它是在 cron 作业中完成的,而不是在登录时立即完成的。
更新:看起来我将不得不更新 moodlelib 和外部数据库插件,如果没有人发布,我会发布我的解决方案。
由于没有人回复,这是我能想到的最好的。我对*UPDATE有自己的评论,所以你知道我在哪里更新了代码。
在 ''moodle''lib''moodlelib 下.php(不幸的是,由于身份验证调用会触发重复创建,我不得不更新此文件)。
1) 更新功能 authenticate_user_login();将第 4342 - 4382 行替换为:
$authsenabled = get_enabled_auth_plugins();
// *UPDATED - begin
$authplugin = get_auth_plugin('DB');
$userinfo = ($authplugin->get_userinfo($username)) ? $authplugin->get_userinfo($username) : 0;
// *UPDATED - end
// *UPDATED - added second elseif
if ($user = get_complete_user_data('username', $username, $CFG->mnet_localhost_id)) {
// Use manual if auth not set.
$auth = empty($user->auth) ? 'manual' : $user->auth;
if (!empty($user->suspended)) {
add_to_log(SITEID, 'login', 'error', 'index.php', $username);
error_log('[client '.getremoteaddr()."] $CFG->wwwroot Suspended Login: $username ".$_SERVER['HTTP_USER_AGENT']);
$failurereason = AUTH_LOGIN_SUSPENDED;
return false;
}
if ($auth=='nologin' or !is_enabled_auth($auth)) {
add_to_log(SITEID, 'login', 'error', 'index.php', $username);
error_log('[client '.getremoteaddr()."] $CFG->wwwroot Disabled Login: $username ".$_SERVER['HTTP_USER_AGENT']);
// Legacy way to suspend user.
$failurereason = AUTH_LOGIN_SUSPENDED;
return false;
}
$auths = array($auth);
}
elseif ($user = get_complete_user_data('idnumber', $userinfo['idnumber'], $CFG->mnet_localhost_id)) {
$auth = empty($user->auth) ? 'manual' : $user->auth; // use manual if auth not set
if (!empty($user->suspended)) {
add_to_log(SITEID, 'login', 'error', 'index.php', $username);
error_log('[client '.getremoteaddr()."] $CFG->wwwroot Suspended Login: $username ".$_SERVER['HTTP_USER_AGENT']);
$failurereason = AUTH_LOGIN_SUSPENDED;
return false;
}
if ($auth=='nologin' or !is_enabled_auth($auth)) {
add_to_log(SITEID, 'login', 'error', 'index.php', $username);
error_log('[client '.getremoteaddr()."] $CFG->wwwroot Disabled Login: $username ".$_SERVER['HTTP_USER_AGENT']);
$failurereason = AUTH_LOGIN_SUSPENDED; // Legacy way to suspend user.
return false;
}
$auths = array($auth);
}
else {
// Check if there's a deleted record (cheaply), this should not happen because we mangle usernames in delete_user().
if ($DB->get_field('user', 'id', array('username' => $username, 'mnethostid' => $CFG->mnet_localhost_id, 'deleted' => 1))) {
error_log('[client '.getremoteaddr()."] $CFG->wwwroot Deleted Login: $username ".$_SERVER['HTTP_USER_AGENT']);
$failurereason = AUTH_LOGIN_NOUSER;
return false;
}
// Do not try to authenticate non-existent accounts when user creation is not disabled.
if (!empty($CFG->authpreventaccountcreation)) {
add_to_log(SITEID, 'login', 'error', 'index.php', $username);
error_log('[client '.getremoteaddr()."] $CFG->wwwroot Unknown user, can not create new accounts: $username ".$_SERVER['HTTP_USER_AGENT']);
$failurereason = AUTH_LOGIN_NOUSER;
return false;
}
// User does not exist.
$auths = $authsenabled;
$user = new stdClass();
$user->id = 0;
}
2) 相同的功能,将 4408 - 4427 行替换为:
if ($user->id) {
// User already exists in database.
if (empty($user->auth)) {
// For some reason auth isn't set yet.
// *UPDATED $DB->set_field('user', 'auth', $auth, array('username'=>$username));
$DB->set_field('user', 'auth', $auth, array('idnumber'=>$user->idnumber));
$user->auth = $auth;
}
// If the existing hash is using an out-of-date algorithm (or the legacy md5 algorithm), then we should update to
// the current hash algorithm while we have access to the user's password.
update_internal_user_password($user, $password);
if ($authplugin->is_synchronised_with_external()) {
// Update user record from external DB.
// *UPDATED $user = update_user_record($username);
$user = $authplugin->update_user_record($username, $user->idnumber);
}
} else {
// Create account, we verified above that user creation is allowed.
$user = create_user_record($username, $password, $auth);
}
在 ''moodle''auth''db''auth.php(外部数据库插件 Lib) 下
1) 更新函数 update_user_record() 以接收 IDNUMBER 参数:
function update_user_record($username, $idnumber='', $updatekeys=false) {
2) 将第 512 行替换为:
$user = $DB->get_record('user', array('idnumber'=>$idnumber, 'mnethostid'=>$CFG->mnet_localhost_id));
所以现在,moodle lib 下的主要函数将通过用户名检查用户是否存在,如果没有,则检查用户 ID 是否存在......如果是这样,它将使用来自外部数据库的新信息更新用户的信息。对我来说,它在 Moodle 2.4 和 2.6 上运行良好。
这是一个相当古老的答案,但有一个不需要手动修补的替代方案。
OP 使用电子邮件地址(而不是任意用户名)来标识用户。可以通过将站点管理>插件>身份验证>管理身份验证>允许通过电子邮件登录 (authloginviaemail
) 设置为 true 来维护此行为。现在,用户名可以由(稳定的)外部数据库 ID 填充。 因此,更改电子邮件地址不会导致新帐户。