使用 WordPress REST API 通过 AJAX 更改密码
Posted
技术标签:
【中文标题】使用 WordPress REST API 通过 AJAX 更改密码【英文标题】:Changing Password via AJAX with the WordPress REST API 【发布时间】:2018-01-07 01:22:35 【问题描述】:我正在使用 WordPress REST API 构建密码更改表单。用户输入一个新密码,然后通过 AJAX 将其提交到执行此操作的自定义端点:
$userID = get_current_user_id();
wp_set_password($password, $userID);
//Log user in and update auth cookie
wp_set_current_user($userID);
wp_set_auth_cookie($userID);
//Set the cookie immediately
$_COOKIE[AUTH_COOKIE] = wp_generate_auth_cookie($userID, 2 * DAY_IN_SECONDS);
//Return fresh nonce
return new WP_Rest_Response(array(
'nonce' => wp_create_nonce('wp_rest')
));
端点应该自动让用户登录并返回一个新的随机数,这样他们就不必使用新密码再次登录。
问题是返回的nonce完全一样,是无效的。我只能在页面刷新后获得新的随机数。 WordPress 用来生成 nonce 的一些 $_COOKIE
或 $_SESSION
变量似乎在页面刷新之前不会更新。
感谢您的帮助。
【问题讨论】:
查看此解决方案***.com/questions/42179869/… 【参考方案1】:WordPress 似乎有一些 $_COOKIE 或 $_SESSION 变量 依赖于生成随机数直到页面才被更新 刷新。
是的,它是LOGGED_IN_COOKIE
,默认为:
'wordpress_logged_in_' . COOKIEHASH
看看:
$token = wp_get_session_token();
in wp_create_nonce()
$cookie = wp_parse_auth_cookie( '', 'logged_in' );
in wp_get_session_token()
$cookie_name = LOGGED_IN_COOKIE;
in wp_parse_auth_cookie()
因此您将替换此代码:(我不会为此使用 wp_generate_auth_cookie()
;而是使用已通过 wp_set_auth_cookie()
生成的代码)
//Set the cookie immediately
$_COOKIE[AUTH_COOKIE] = wp_generate_auth_cookie($userID, 2 * DAY_IN_SECONDS);
..用这个:
$_set_cookies = true; // for the closures
// Set the (secure) auth cookie immediately. We need only the first and last
// arguments; hence I renamed the other three, namely `$a`, `$b`, and `$c`.
add_action( 'set_auth_cookie', function( $auth_cookie, $a, $b, $c, $scheme ) use( $_set_cookies )
if ( $_set_cookies )
$_COOKIE[ 'secure_auth' === $scheme ? SECURE_AUTH_COOKIE : AUTH_COOKIE ] = $auth_cookie;
, 10, 5 );
// Set the logged-in cookie immediately. `wp_create_nonce()` relies upon this
// cookie; hence, we must also set it.
add_action( 'set_logged_in_cookie', function( $logged_in_cookie ) use( $_set_cookies )
if ( $_set_cookies )
$_COOKIE[ LOGGED_IN_COOKIE ] = $logged_in_cookie;
);
// Set cookies.
wp_set_auth_cookie($userID);
$_set_cookies = false;
工作示例(在 WordPress 4.9.5 上测试)
PHP/WP REST API
function myplugin__change_password( $password, $userID )
//$userID = get_current_user_id();
wp_set_password($password, $userID);
// Log user in.
wp_set_current_user($userID);
$_set_cookies = true; // for the closures
// Set the (secure) auth cookie immediately. We need only the first and last
// arguments; hence I renamed the other three, namely `$a`, `$b`, and `$c`.
add_action( 'set_auth_cookie', function( $auth_cookie, $a, $b, $c, $scheme ) use( $_set_cookies )
if ( $_set_cookies )
$_COOKIE[ 'secure_auth' === $scheme ? SECURE_AUTH_COOKIE : AUTH_COOKIE ] = $auth_cookie;
, 10, 5 );
// Set the logged-in cookie immediately. `wp_create_nonce()` relies upon this
// cookie; hence, we must also set it.
add_action( 'set_logged_in_cookie', function( $logged_in_cookie ) use( $_set_cookies )
if ( $_set_cookies )
$_COOKIE[ LOGGED_IN_COOKIE ] = $logged_in_cookie;
);
// Set cookies.
wp_set_auth_cookie($userID);
$_set_cookies = false;
//Return fresh nonce
return new WP_Rest_Response(array(
'nonce' => wp_create_nonce('wp_rest'),
'status' => 'password_changed',
));
function myplugin_change_password( WP_REST_Request $request )
$old_pwd = $request->get_param( 'old_pwd' );
$new_pwd = $request->get_param( 'new_pwd' );
$user = wp_get_current_user();
if ( ! wp_check_password( $old_pwd, $user->user_pass, $user->ID ) )
return new WP_Error( 'wrong_password', 'Old password incorrect' );
if ( $old_pwd !== $new_pwd )
return myplugin__change_password( $new_pwd, $user->ID );
return new WP_Rest_Response( [
'nonce' => wp_create_nonce( 'wp_rest' ),
'status' => 'passwords_equal',
], 200 );
add_action( 'rest_api_init', function()
register_rest_route( 'myplugin/v1', '/change-password', [
'methods' => 'POST',
'callback' => 'myplugin_change_password',
'args' => [
'old_pwd' => [
'type' => 'string',
'validate_callback' => function( $param )
return ! empty( $param );
],
'new_pwd' => [
'type' => 'string',
'validate_callback' => function( $param )
return ! empty( $param );
],
],
'permission_callback' => function()
// Only logged-in users.
return current_user_can( 'read' );
,
] );
);
HTML / 表单
<fieldset>
<legend>Change Password</legend>
<p>
To change your password, please enter your old or current password.
</p>
<label>
Old Password:
<input id="old_passwd">
</label>
<label>
New Password:
<input id="new_passwd">
</label>
<label>
Old nonce: (read-only)
<input id="old_nonce" value="<?= wp_create_nonce( 'wp_rest' ) ?>"
readonly disabled>
</label>
<label>
New nonce: (read-only)
<input id="new_nonce" readonly disabled>
</label>
<button id="go" onclick="change_passwd()">Change</button>
</fieldset>
<div id="rest-res"><!-- AJAX response goes here --></div>
jQuery / AJAX
function change_passwd()
var apiurl = '/wp-json/myplugin/v1/change-password',
$ = jQuery;
$.post( apiurl,
old_pwd: $( '#old_passwd' ).val(),
new_pwd: $( '#new_passwd' ).val(),
_wpnonce: $( '#new_nonce' ).val() || $( '#old_nonce' ).val()
, function( res )
$( '#new_nonce' ).val( res.nonce );
// Update the global nonce for scripts using the `wp-api` script.
if ( 'object' === typeof wpApiSettings )
wpApiSettings.nonce = res.nonce;
$( '#rest-res' ).html( '<b>Password changed successfully.</b>' );
, 'json' ).fail( function( xhr )
try
var res = JSON.parse( xhr.responseText );
catch ( err )
return;
if ( res.code )
$( '#rest-res' ).html( '<b>[ERROR]</b> ' + res.message );
);
【讨论】:
【参考方案2】:您需要将随机数通过 X-WP-Nonce
标头与您的 AJAX 请求一起传递。比如:
beforeSend: function ( xhr )
xhr.setRequestHeader( 'X-WP-Nonce', localizedScript.nonce );
localizedScript
是您的 nonce 本地化的脚本。有关本地化的更多信息,请参阅法典。 注意localizedScript
方法不是必需的。
如果没有localizedSript
,您的 AJAX 可能类似于以下内容:
var _nonce = "<?php echo wp_create_nonce( 'wp_rest' ); ?>";
$.ajax(
type: 'POST',
url: url_path,
data: ,
dataType: 'json',
beforeSend: function ( xhr )
xhr.setRequestHeader( 'X-WP-Nonce', _nonce );
);
显然复制上面的那个确切的脚本不会为你完成它,但这基本上是你成功传递随机数的方式。
【讨论】:
以上是关于使用 WordPress REST API 通过 AJAX 更改密码的主要内容,如果未能解决你的问题,请参考以下文章
使用 Wordpress Rest API JS 填充 ACF 字段