WordPress Rest API 重置用户密码时要求输入原密码的方法

WordPress Rest API默认只需要用户有权限便可重置用户密码。

对于前后端分离的项目,为了安全,重置密码一般要求用户输入原密码。

基础原理是在更新用户密码前进行“拦截”,额外逻辑判断。

用到的钩子Hook是rest_pre_insert_user,详细用法如下:

<?php

add_filter( 'rest_pre_insert_user', 'pury_custom_rest_pre_insert_user', 10, 2 );

function pury_custom_rest_pre_insert_user( $prepared_user, $request ) {
    $user_id = get_current_user_id();
    $target_user_id = (int) $prepared_user->ID;

    // 如果参数用没有密码字段,直接返回正常流程
    if (!isset($prepared_user->user_pass) ) return $prepared_user;

    $user = get_user_by( 'id', $target_user_id );

    // 创建新用户,单独处理,通常是管理员操作,暂时直接通过,不做额外处理
    // 按需添加逻辑判断
    if (!$user) {
        if (current_user_can('manage_options')) {
            $prepared_user->user_pass = $request['password'];
            return $prepared_user; 
        } else {
            return new WP_Error(
                'no_access',
                __( '无权限!' ),
                array( 'status' => 400 )
            );
        }
    }

    $pwd_c =    $request['current_password'];  // 旧密码
    $pwd_v =    $request['new_password'];      // 重复新密码
    $password = $request['password'];          // 新密码

    if ($password !== $pwd_v) {
        return new WP_Error(
            'error args',
            __( '两次新密码不一致,请重新输入!' ),
            array( 'status' => 400 )
        );
    }

    global $wpdb;
    $user_data = $wpdb->get_row($wpdb->prepare(
        "SELECT user_pass FROM $wpdb->users WHERE ID=%d", $target_user_id));
    $user_pass = $user_data->user_pass;
    $check = wp_check_password($pwd_c, $user_pass, $target_user_id);

    // 验证旧密码
    if (!$check) {
        return new WP_Error(
            'error args',
            __( '旧密码不正确,请重新输入!' ),
            array( 'status' => 400 )
        );
    }

    $check = wp_check_password($password, $user_pass, $target_user_id);

    if ($check) {
        return new WP_Error(
            'error args',
            __( '新密码不能与旧密码相同,请重新输入!' ),
            array( 'status' => 400 )
        );
    }

    // 全部通过,返回正常流程
    $prepared_user->user_pass = $password;
    return $prepared_user;
}

重置密码需要传入三个参数:原密码(current_password)、新密码(password)和重复新密码(new_password)。其中,参数password必须不变,因为内核会用到,其他两个可自定义。

注释比较详细,注意辨别。

然后,需要在内核主流程中插入错误验证判断,文件位置:
/wp-includes/rest-api/endpoints/class-wp-rest-users-controller.php

一共有两处:

<?php
		$user = $this->prepare_item_for_database( $request );

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

(版权归cpury.com所有,转载请注明出处。)