WordPress Rest API默认情况下,重置密码与修改用户其他属性(如昵称等)一样,只要有权限便可操作。
但对于前后端分离的项目,重置密码时有必要让用户输入旧密码,提升安全性。
推荐使用钩子Hookrest_pre_insert_user
,在执行更新用户密码前进行额外逻辑判断。
重置密码需要传入三个参数:旧密码(old_password
)、新密码(password
)和重复新密码(repeat_password
)。其中,为避免麻烦,参数password
名称必须保持不变,因为内核会用到,其他两个可自定义。
效果如图:
第一步:应用钩子
主要功能:
- 验证旧密码正确
- 验证新密码和重复新密码保持一致
- 验证新密码与旧密码不一样
<?php
add_filter( 'rest_pre_insert_user', 'szwzjx_custom_rest_pre_insert_user', 10, 2 );
function szwzjx_custom_rest_pre_insert_user( $prepared_user, $request ) {
// 目标用户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['old_password']; // 旧密码
$pwd_v = $request['repeat_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;
}
第二步:拓展主流程
在内核主流程中插入错误验证判断,文件位置:
/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;
}
此文件也是钩子rest_pre_insert_user
实际应用的地方。
protected function prepare_item_for_database( $request ) {
$prepared_user = new stdClass;
// ....
return apply_filters( 'rest_pre_insert_user', $prepared_user, $request );
}
前端调用接口示例:
import axios from 'axios';
import Session from './session';
// 重置自己密码
const reset_password = () => {
const option = {
old_password: '123456', // 当前密码
password: 'hello', // 新密码
repeat_password: 'hello' // 重复新密码
};
const sessionKey = Session.get();
const headers = { 'Authorization': 'Bearer' + sessionKey };
const reqUrl = 'wp-json/wp/v2/users/me';
return axios.post(reqUrl, option, { headers });
}
注
:对WordPress内核有微调,请谨慎参考。