wordpress忘记密码重置密码方法以及相关登录源码解读

一、重置密码

安装最新版 wordpress-5.4.2-zh_CN.zip 很长时间未维护,登录时候突然发现密码忘记了,记录下解决办法吧。

重置登录密码为:123456
UPDATE wp_users SET user_pass = '$P$BiPHCyMrQlCHFzG/1ftoDdulGpfsoP0' WHERE ID =1
使用重置的登录后台设置安全密码
进入登录 后台 >> 用户 >> 所有用户 选项卡 ;点击 编辑 按钮,找到 新密码 >> 生成密码 按钮,输入想设置的密码,最后 更新个人资料

二、登录源码解读

1. 登录控制器方法

在 wp-login.php 1174 行 — 查询数据库用户信息
// If the user wants SSL but the session is not SSL, force a secure cookie.
if ( ! empty( $_POST[‘log’] ) && ! force_ssl_admin() ) {
$user_name = sanitize_user( wp_unslash( $_POST[‘log’] ) );
$user = get_user_by( ‘login’, $user_name ); // 这里查询数据库用户信息
// …
}
// …
$user = wp_signon( array(), $secure_cookie ); // 这里校验密码
其中 get_user_by() 方法最终执行类似下面的 SQL:
$user = $wpdb->get_row(
$wpdb->prepare(
“SELECT * FROM $wpdb->users WHERE $db_field = %s LIMIT 1”,
$value
)
);

2. 接下来是校验密码的逻辑:

主要使用 wp_signon() 方法获取;代码在 wp-includes/user.php 文件中第 95 行

$user = wp_authenticate( $credentials['user_login'], $credentials['user_password'] ); 

方法最终会调用 wp-includes/pluggable.php 文件的

 function wp_check_password( $password, $hash, $user_id = '' ) {} // 去检测密码。
function wp_signon( $credentials = array(), $secure_cookie = '' ) {
    // ...
    $user = wp_authenticate( $credentials['user_login'], $credentials['user_password'] );

    if ( is_wp_error( $user ) ) {
        return $user;
    }
    // ...
    return $user;
}

wp-includes/pluggable.php >> 2405 行

$check = $wp_hasher->CheckPassword( $password, $hash ); 

方法,调用的是 wp-includes/class-phpass.php 文件的 CheckPassword()

function wp_check_password( $password, $hash, $user_id = '' ) {
    global $wp_hasher;
    // ...
    $check = $wp_hasher->CheckPassword( $password, $hash );
}

wp-includes/class-phpass.php 文件的 CheckPassword

CheckPassword() 方法又调用内部

$hash = $this->crypt_private($password, $stored_hash);

crypt_private 继续调用 $output .= t h i s − > e n c o d e 64 ( this->encode64( this>encode64(input, 6); 内部方法,最终返回的 o u t p u t = ′ output = ' output=P$BlQ4L10EWkfoyGXC0EtVK.KdwW9WxW.'; 类似的字符串。

最终比较 return $hash === $stored_hash; 这两个字符串是否全等。

class PasswordHash {

    function CheckPassword($password, $stored_hash)
    {
        if ( strlen( $password ) > 4096 ) {
            return false;
        }

        $hash = $this->crypt_private($password, $stored_hash);
        if ($hash[0] == '*')
            $hash = crypt($password, $stored_hash);

        return $hash === $stored_hash;
    }

    function crypt_private($password, $setting)
    {
        $output = '*0';
        if (substr($setting, 0, 2) == $output)
            $output = '*1';

        $id = substr($setting, 0, 3);
        # We use "$P$", phpBB3 uses "$H$" for the same thing
        if ($id != '$P$' && $id != '$H$')
            return $output;

        $count_log2 = strpos($this->itoa64, $setting[3]);
        if ($count_log2 < 7 || $count_log2 > 30)
            return $output;

        $count = 1 << $count_log2;

        $salt = substr($setting, 4, 8);
        if (strlen($salt) != 8)
            return $output;

        # We're kind of forced to use MD5 here since it's the only
        # cryptographic primitive available in all versions of PHP
        # currently in use.  To implement our own low-level crypto
        # in PHP would result in much worse performance and
        # consequently in lower iteration counts and hashes that are
        # quicker to crack (by non-PHP code).
        if (PHP_VERSION >= '5') {
            $hash = md5($salt . $password, TRUE);
            do {
                $hash = md5($hash . $password, TRUE);
            } while (--$count);
        } else {
            $hash = pack('H*', md5($salt . $password));
            do {
                $hash = pack('H*', md5($hash . $password));
            } while (--$count);
        }

        $output = substr($setting, 0, 12);
        $output .= $this->encode64($hash, 16);

        return $output;
    }

    function crypt_private($password, $setting)
    {
        $output = '*0';
        if (substr($setting, 0, 2) == $output)
            $output = '*1';

        $id = substr($setting, 0, 3);
        # We use "$P$", phpBB3 uses "$H$" for the same thing
        if ($id != '$P$' && $id != '$H$')
            return $output;

        $count_log2 = strpos($this->itoa64, $setting[3]);
        if ($count_log2 < 7 || $count_log2 > 30)
            return $output;

        $count = 1 << $count_log2;

        $salt = substr($setting, 4, 8);
        if (strlen($salt) != 8)
            return $output;

        # We're kind of forced to use MD5 here since it's the only
        # cryptographic primitive available in all versions of PHP
        # currently in use.  To implement our own low-level crypto
        # in PHP would result in much worse performance and
        # consequently in lower iteration counts and hashes that are
        # quicker to crack (by non-PHP code).
        if (PHP_VERSION >= '5') {
            $hash = md5($salt . $password, TRUE);
            do {
                $hash = md5($hash . $password, TRUE);
            } while (--$count);
        } else {
            $hash = pack('H*', md5($salt . $password));
            do {
                $hash = pack('H*', md5($hash . $password));
            } while (--$count);
        }

        $output = substr($setting, 0, 12);
        $output .= $this->encode64($hash, 16);

        return $output;
    }

    function encode64($input, $count)
    {
        $output = '';
        $i = 0;
        do {
            $value = ord($input[$i++]);
            $output .= $this->itoa64[$value & 0x3f];
            if ($i < $count)
                $value |= ord($input[$i]) << 8;
            $output .= $this->itoa64[($value >> 6) & 0x3f];
            if ($i++ >= $count)
                break;
            if ($i < $count)
                $value |= ord($input[$i]) << 16;
            $output .= $this->itoa64[($value >> 12) & 0x3f];
            if ($i++ >= $count)
                break;
            $output .= $this->itoa64[($value >> 18) & 0x3f];
        } while ($i < $count);

        return $output;
    }
}

三、总结:

最终加密的算法就是在 wp-includes/class-phpass.php 文件的 crypt_private 方法,其中 $count = 1 << $count_log2; 决定了 md5 的 hash 值,有空可以读读上面的逻辑。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值