For those that arrive from Google: You probably shouldn\'t get the nonces from the REST API, unless you really know what you\'re doing. Cookie-based authentication with the REST API is only meant for plugins and themes. For a single page application, you should probably use OAuth.
这个问题的存在是因为文档不清楚在构建单页应用程序时应该如何进行身份验证,JWT并不真正适合web应用程序,OAuth比基于cookie的身份验证更难实现。
<小时>The handbook 有一个关于主干JavaScript客户端如何处理nonce的示例,如果我遵循该示例,我会得到一个内置端点(如/wp/v2/posts)接受的nonce。
\\wp_localize_script("client-js", "theme", [
\'nonce\' => wp_create_nonce(\'wp_rest\'),
\'user\' => get_current_user_id(),
]);
然而,使用主干网是不可能的,主题也是不可能的,因此我编写了以下插件:
<?php
/*
Plugin Name: Nonce Endpoint
*/
add_action(\'rest_api_init\', function () {
$user = get_current_user_id();
register_rest_route(\'nonce/v1\', \'get\', [
\'methods\' => \'GET\',
\'callback\' => function () use ($user) {
return [
\'nonce\' => wp_create_nonce(\'wp_rest\'),
\'user\' => $user,
];
},
]);
register_rest_route(\'nonce/v1\', \'verify\', [
\'methods\' => \'GET\',
\'callback\' => function () use ($user) {
$nonce = !empty($_GET[\'nonce\']) ? $_GET[\'nonce\'] : false;
return [
\'valid\' => (bool) wp_verify_nonce($nonce, \'wp_rest\'),
\'user\' => $user,
];
},
]);
});
我对JavaScript控制台进行了一些修改,并编写了以下内容:
var main = async () => { // var because it can be redefined
const nonceReq = await fetch(\'/wp-json/nonce/v1/get\', { credentials: \'include\' })
const nonceResp = await nonceReq.json()
const nonceValidReq = await fetch(`/wp-json/nonce/v1/verify?nonce=${nonceResp.nonce}`, { credentials: \'include\' })
const nonceValidResp = await nonceValidReq.json()
const addPost = (nonce) => fetch(\'/wp-json/wp/v2/posts\', {
method: \'POST\',
credentials: \'include\',
body: JSON.stringify({
title: `Test ${Date.now()}`,
content: \'Test\',
}),
headers: {
\'X-WP-Nonce\': nonce,
\'content-type\': \'application/json\'
},
}).then(r => r.json()).then(console.log)
console.log(nonceResp.nonce, nonceResp.user, nonceValidResp)
console.log(theme.nonce, theme.user)
addPost(nonceResp.nonce)
addPost(theme.nonce)
}
main()
预期的结果是两个新职位,但我得到
Cookie nonce is invalid
从第一个开始,第二个成功创建post。这可能是因为nonces不同,但为什么呢?我在两个请求中都以同一用户身份登录。
如果我的方法是错误的,我应该如何获得nonce?
Edit:
我试着在没有太多运气的情况下与环球足球队混战。利用wp\\u加载的操作更幸运:
<?php
/*
Plugin Name: Nonce Endpoint
*/
$nonce = \'invalid\';
add_action(\'wp_loaded\', function () {
global $nonce;
$nonce = wp_create_nonce(\'wp_rest\');
});
add_action(\'rest_api_init\', function () {
$user = get_current_user_id();
register_rest_route(\'nonce/v1\', \'get\', [
\'methods\' => \'GET\',
\'callback\' => function () use ($user) {
return [
\'nonce\' => $GLOBALS[\'nonce\'],
\'user\' => $user,
];
},
]);
register_rest_route(\'nonce/v1\', \'verify\', [
\'methods\' => \'GET\',
\'callback\' => function () use ($user) {
$nonce = !empty($_GET[\'nonce\']) ? $_GET[\'nonce\'] : false;
error_log("verify $nonce $user");
return [
\'valid\' => (bool) wp_verify_nonce($nonce, \'wp_rest\'),
\'user\' => $user,
];
},
]);
});
现在,当我运行上面的JavaScript时,创建了两篇文章,但验证端点失败了!
我立即去调试wp\\u verify\\u:
function wp_verify_nonce( $nonce, $action = -1 ) {
$nonce = (string) $nonce;
$user = wp_get_current_user();
$uid = (int) $user->ID; // This is 0, even though the verify endpoint says I\'m logged in as user 2!
我添加了一些日志记录
// Nonce generated 0-12 hours ago
$expected = substr( wp_hash( $i . \'|\' . $action . \'|\' . $uid . \'|\' . $token, \'nonce\'), -12, 10 );
error_log("expected 1 $expected received $nonce uid $uid action $action");
if ( hash_equals( $expected, $nonce ) ) {
return 1;
}
// Nonce generated 12-24 hours ago
$expected = substr( wp_hash( ( $i - 1 ) . \'|\' . $action . \'|\' . $uid . \'|\' . $token, \'nonce\' ), -12, 10 );
error_log("expected 2 $expected received $nonce uid $uid action $action");
if ( hash_equals( $expected, $nonce ) ) {
return 2;
}
JavaScript代码现在会生成以下条目。如您所见,调用verify端点时,uid为0。
[01-Mar-2018 11:41:57 UTC] verify 716087f772 2
[01-Mar-2018 11:41:57 UTC] expected 1 b35fa18521 received 716087f772 uid 0 action wp_rest
[01-Mar-2018 11:41:57 UTC] expected 2 dd35d95cbd received 716087f772 uid 0 action wp_rest
[01-Mar-2018 11:41:58 UTC] expected 1 716087f772 received 716087f772 uid 2 action wp_rest
[01-Mar-2018 11:41:58 UTC] expected 1 716087f772 received 716087f772 uid 2 action wp_rest