CMS, 原创

Moodle开源CMS的加密方式 自己开发module判断用户名和密码是否正确

最近Moodle的密码已经是60位长度以$2y$10$开头的密码了,密码长60位 前面是“$2y$”类似这种字符开头的话 使用的是 crypt() 的加密方式, 在php5.5以上的版本中, 系统带的 password_hash($password, $salt); 来加密的,这个密码验证只能通过 password_verify() 函数来验证,但因为大部分php环境都还没有那么高,或者是为了兼容低版本的PHP, 一般CMS都会判断函数是不是存在,在低版本不存在这些函数的时候都会自定义出来使用。

Moodle 2.6 在验证用户的过程中我们只需要使用他们自己已经定义好的函数就行了,那么真么验证我们提供的用户名和密码是不是正确呢?

1.根据用户名$username去查找是否存在这个用户

$user = $DB->get_record('user', array('username'=>$username));

如果$user存在那就说明用户已经找到了,那密码是不是正确呢,如我们提供的密码为$password,那么

validate_internal_user_password($user,$password);

如果这个函数返回true则验证成功,否则验证失败。 这个函数是可以直接使用的哦,关于validate_internal_user_password的定义我们可以再<moodle 根目录>/lib/moodlelib.php中找到。

以上内容在我们使用moodle验证用户名和密码的时候就能够正确通过了,下面附这个函数的定义。

/**
 * Compare password against hash stored in user object to determine if it is valid.
 *
 * If necessary it also updates the stored hash to the current format.
 *
 * @param stdClass $user (Password property may be updated).
 * @param string $password Plain text password.
 * @return bool True if password is valid.
 */
function validate_internal_user_password($user, $password) {
    global $CFG;
    require_once($CFG->libdir.'/password_compat/lib/password.php');

    if ($user->password === AUTH_PASSWORD_NOT_CACHED) {
        // Internal password is not used at all, it can not validate.
        return false;
    }

    // If hash isn't a legacy (md5) hash, validate using the library function.
    if (!password_is_legacy_hash($user->password)) {
        return password_verify($password, $user->password);
    }

    // Otherwise we need to check for a legacy (md5) hash instead. If the hash
    // is valid we can then update it to the new algorithm.

    $sitesalt = isset($CFG->passwordsaltmain) ? $CFG->passwordsaltmain : '';
    $validated = false;

    if ($user->password === md5($password.$sitesalt)
            or $user->password === md5($password)
            or $user->password === md5(addslashes($password).$sitesalt)
            or $user->password === md5(addslashes($password))) {
        // Note: we are intentionally using the addslashes() here because we
        //       need to accept old password hashes of passwords with magic quotes.
        $validated = true;

    } else {
        for ($i=1; $i<=20; $i++) { // 20 alternative salts should be enough, right?
            $alt = 'passwordsaltalt'.$i;
            if (!empty($CFG->$alt)) {
                if ($user->password === md5($password.$CFG->$alt) or $user->password === md5(addslashes($password).$CFG->$alt)) {
                    $validated = true;
                    break;
                }
            }
        }
    }

    if ($validated) {
        // If the password matches the existing md5 hash, update to the
        // current hash algorithm while we have access to the user's password.
        update_internal_user_password($user, $password);
    }

    return $validated;
}

其中在这个函数中调用了另外一个函数password_is_legacy_hash用来判断是不是32为密码,不是32位密码则使用password_verify($password, $user->password);验证。

function password_is_legacy_hash($password) {
    return (bool) preg_match('/^[0-9a-f]{32}$/', $password);
}

但是 password_verify并非只可以验证60位长度的哦,还可以是其他长度的。

(11609)

Related Post