Đối với những người đến từ Google: Có lẽ bạn không nên lấy nonces từ API REST , trừ khi bạn thực sự biết bạn đang làm gì. Xác thực dựa trên cookie với API REST chỉ có ý nghĩa đối với các plugin và chủ đề. Đối với một ứng dụng trang duy nhất, có lẽ bạn nên sử dụng OAuth .
Câu hỏi này tồn tại bởi vì tài liệu không / không rõ ràng về cách bạn thực sự nên xác thực khi xây dựng các ứng dụng trang đơn, JWTs không thực sự phù hợp với các ứng dụng web và OAuth khó thực hiện hơn so với xác thực dựa trên cookie.
Cuốn cẩm nang có một ví dụ về cách máy khách JavaScript xương sống xử lý các nonces và nếu tôi làm theo ví dụ này, tôi nhận được một thông báo mà các điểm cuối được xây dựng như / wp / v2 / post chấp nhận.
\wp_localize_script("client-js", "theme", [
'nonce' => wp_create_nonce('wp_rest'),
'user' => get_current_user_id(),
]);
Tuy nhiên, sử dụng Backbone là không cần thiết, và các chủ đề cũng vậy, vì vậy tôi đã viết plugin sau:
<?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,
];
},
]);
});
Tôi đã sửa lại trong bảng điều khiển JavaScript một chút và viết như sau:
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()
Kết quả dự kiến là hai bài viết mới, nhưng tôi nhận được Cookie nonce is invalid
từ bài đầu tiên, và bài thứ hai tạo ra bài thành công. Đó có lẽ là do các nonces khác nhau, nhưng tại sao? Tôi đã đăng nhập với cùng một người dùng trong cả hai yêu cầu.
Nếu cách tiếp cận của tôi là sai, làm thế nào tôi có được nonce?
Chỉnh sửa :
Tôi đã cố gắng gây rối với toàn cầu mà không gặp nhiều may mắn . Có một chút may mắn hơn bằng cách sử dụng hành động wp_loaded:
<?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,
];
},
]);
});
Bây giờ khi tôi chạy JavaScript ở trên, hai bài đăng được tạo, nhưng điểm cuối xác minh không thành công!
Tôi đã đi đến gỡ lỗi wp_verify_nonce:
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!
Tôi đã thêm một số đăng nhập
// 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;
}
và mã JavaScript bây giờ dẫn đến các mục sau. Như bạn có thể thấy, khi điểm cuối xác minh được gọi, uid là 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