TLDR:如何强制返回一个新的nonce,以便AJAX在不刷新页面的情况下工作
从以下位置开始
Nonces and Ajax request to REST API and verification 我实现了Nonce功能,具有回调权限,路由的“意图”现在是安全的。
我将Axios排队,将wp\\u rest nonce作为本地脚本设置。
// Register custom variables for the AJAX script.
wp_localize_script( \'axios\', \'axiosScriptVars\', [
\'root\' => esc_url_raw( rest_url() ),
\'nonce\' => wp_create_nonce( \'wp_rest\' ),
]);
我使用axiosScriptVars设置Ajax标头。暂时的。我发布了这篇文章。我从REST\\U API端点的响应中返回一个NONCE,并更新我的Ajax头,为下一篇文章做好准备。。。
我的登录和注销路由示例:
function ajax_logout() {
try {
wp_logout();
$nonce = wp_create_nonce( \'wp_rest\' );
return array(\'loggedin\'=>false, \'message\'=>__(\'Logged out successfully\'), \'name\'=>false, \'email\'=>false, \'nonce\'=>$nonce );
} catch (Exception $e) {
echo \'Caught exception: \', $e->getMessage(), "\\n";
die;
}
}
function ajax_login(){
$_POST = json_decode(file_get_contents("php://input"),true);
$info = array();
$info[\'user_login\'] = !empty($_POST[\'username\']) ? sanitize_text_field( $_POST[\'username\'] ) : null;
$info[\'user_password\'] = !empty( $_POST[\'password\'] ) ? sanitize_text_field( $_POST[\'password\'] ) : null;
$info[\'remember\'] = true;
$user = wp_signon( $info, true );
$nonce = wp_create_nonce( \'wp_rest\' );
if ( is_wp_error($user) ){
return array(\'loggedin\'=>false, \'message\'=>__(\'Wrong username or password.\'), \'name\'=>false, \'email\'=>false, \'nonce\'=>$nonce );
} else {
return array(\'loggedin\'=>true, \'message\'=>__(\'Login successful\'), \'name\'=>$user->data->display_name, \'email\'=>$user->data->user_email, \'nonce\'=>$nonce );
}
}
add_action( \'rest_api_init\', function () {
register_rest_route( \'rw-user/v1\', \'/log-in\', array(
\'methods\' => \'POST\',
\'callback\' => \'ajax_login\',
\'permission_callback\' => \'__return_true\'
));
register_rest_route(\'rw-user/v1\',\'/log-out\', array(
\'methods\' => \'POST\',
"callback" => \'ajax_logout\',
"permission_callback" => function () {
return current_user_can( \'read\' );
}
));
});
过帐失败,因为新的NONCE与旧的相同。
所以我认为Wordpress必须在响应头中返回一个新的nonce。。。我查看并查看;x-wp-nonce“;标题-只有它也是相同的!
(我读到一些关于在REST路由中不使用wp\\u json\\u success的内容,因为REST api已经将函数的返回转换为json响应,并设置了正确的头等。)
当我硬刷新页面时,我得到了一个新的nonce,我的AJAX现在可以工作了。。。
如何强制返回一个新的nonce,以便AJAX在不刷新页面的情况下工作?
这篇帖子有点类似-Serving nonces through AJAX is not refreshing nonce, returning 403 error, 但是我在我的代码中看不到任何更改用户和使nonce无效的内容。。。
除非登录路由(现在已登录)更改nonce,否则不会返回该nonce?
编辑
我已经用Sally的答案进行了重构。一切正常(尽管我不得不清除浏览器缓存,因为发生了一些奇怪的事情)。
// https://wordpress.stackexchange.com/questions/377570/identical-wp-rest-nonce-returned-from-rest-api
/* Ajax REST cookie stuff */
// https://remonpel.nl/2018/06/wordpress-rest-api-nonce-sense/
add_action(\'set_logged_in_cookie\', function($cookie_value){
$_COOKIE[ LOGGED_IN_COOKIE ] = $cookie_value;
}, PHP_INT_MAX);
// on log-ou, clear the global $_COOKIE the same way wp_logout() does.
// todo: see if more cookies need this.
add_action(\'clear_auth_cookie\', function(){
$_COOKIE[ LOGGED_IN_COOKIE ] = \' \';
});
/* end Ajax REST cookie stuff */
function ajax_logout() {
wp_logout();
wp_set_current_user(0);
return [
\'loggedin\' => false,
\'message\' => __(\'Logged out successfully\'),
\'name\' => false,
\'email\' => false,
];
}
function ajax_login($request){
$user = wp_signon( array(
\'user_login\' => $request->get_param( \'username\' ),
\'user_password\' => $request->get_param( \'password\' ),
\'remember\' => true,
));
// In case of errors like wrong password, return the error object/data.
if ( is_wp_error( $user ) ) {
$data = [
\'failed\' => $user,
\'nonce\' => wp_create_nonce( \'wp_rest\' ),
];
return new WP_REST_Response($data, 200); // important if you want to display data client side
}
wp_set_current_user( $user->ID ); // super important
return [
\'loggedin\' => is_user_logged_in(),
\'message\' => __(\'Login successful\'),
\'name\' => $user->data->display_name,
\'email\' => $user->data->user_email,
\'nonce\' => wp_create_nonce( \'wp_rest\' ),
];
}
function read_permissions_check() {
// Restrict endpoint to only users who have the edit_posts capability.
// This can be extended or whatever
if ( !current_user_can( \'read\' ) ) {
return new WP_Error( \'rest_forbidden\', esc_html__( \'You shall not pass!\', \'my-text-domain\' ), array( \'status\' => 401 ) );
}
return true;
}
add_action( \'rest_api_init\', function () {
register_rest_route( \'rw-user/v1\', \'/log-in\', array(
\'methods\' => \'POST\',
\'callback\' => \'ajax_login\',
\'permission_callback\' => \'__return_true\',
));
register_rest_route(\'rw-user/v1\',\'/log-out\', array(
\'methods\' => \'POST\',
"callback" => \'ajax_logout\',
\'permission_callback\' => \'read_permissions_check\',
));
});