La funzione wp_get_current_user() non funziona nella callback dell'API REST
Considera la seguente classe.
<?php
class MCQAcademy_Endpoint extends WP_REST_Controller {
/**
* Registra le route per gli oggetti del controller.
*/
public function register_routes() {
$version = '1';
$namespace = 'custompath/v' . $version;
$base = 'endpointbase';
register_rest_route(
$namespace,
'/' . $base,
array(
array(
'methods' => WP_REST_Server::READABLE,
'callback' => array( $this, 'get_items' ),
'permission_callback' => array( $this, 'get_items_permissions_check' ),
'args' => array(),
)
)
);
}
/**
* Ottiene gli elementi
*/
public function get_items( $request ) {
$rs = array(
'data' => array(),
'request' => array(
'lang' => 'en',
),
);
$args = array();
$items = get_posts( $args );
foreach( $items as $item ) {
$itemdata = $this->prepare_item_for_response( $item, $request );
$rs['data'][] = $this->prepare_response_for_collection( $itemdata );
}
$rs['wp_get_current_user'] = wp_get_current_user(); // Non restituisce l'output atteso
return new WP_REST_Response( $rs, 200 );
}
/**
* Verifica se una richiesta ha accesso per ottenere gli elementi
*/
public function get_items_permissions_check( $request ) {
return true; // per renderlo leggibile da tutti
}
/**
* Prepara l'elemento per l'operazione di creazione o aggiornamento
*/
protected function prepare_item_for_database( $request ) {
return $request;
}
/**
* Prepara l'elemento per la risposta REST
*/
public function prepare_item_for_response( $item, $request ) {
$data = array(
'ID' => $item->ID,
'post_content' => wpautop($item->post_content),
'post_title' => $item->post_title,
);
return $data;
}
/**
* Ottiene i parametri di query per le collezioni
*/
public function get_collection_params() {
return array(
'page' => array(
'description' => 'Pagina corrente della collezione.',
'type' => 'integer',
'default' => 1,
'sanitize_callback' => 'absint',
),
'per_page' => array(
'description' => 'Numero massimo di elementi da restituire nel set di risultati.',
'type' => 'integer',
'default' => 10,
'sanitize_callback' => 'absint',
),
'search' => array(
'description' => 'Limita i risultati a quelli che corrispondono a una stringa.',
'type' => 'string',
'sanitize_callback' => 'sanitize_text_field',
),
);
}
// Registra il nostro server REST
public function hook_rest_server(){
add_action( 'rest_api_init', array( $this, 'register_routes' ) );
}
}
$myEndpoint = new MCQAcademy_Endpoint();
$myEndpoint->hook_rest_server();
Tutto funziona correttamente tranne quando si chiama la funzione wp_get_current_user()
nella funzione get_items()
, che restituisce un utente vuoto nonostante l'utente sia loggato
nel sito web.

Essere loggato sul tuo sito web non significa che l'utente sia autenticato nella richiesta REST API, ecco perché non stai ottenendo l'utente corretto o un Id = 0
Dai un'occhiata ai metodi di autenticazione REST API nella documentazione:
https://developer.wordpress.org/rest-api/using-the-rest-api/authentication/
Per gli sviluppatori che effettuano richieste Ajax manuali, il nonce dovrà essere passato con ogni richiesta. L'API utilizza nonce con l'azione impostata su wp_rest. Questi possono poi essere passati all'API tramite il parametro dati _wpnonce (dati POST o nella query per le richieste GET), o tramite l'header X-WP-Nonce. Se non viene fornito alcun nonce, l'API imposterà l'utente corrente su 0, trasformando la richiesta in una richiesta non autenticata, anche se sei loggato in WordPress.
Per l'autenticazione remota consiglio il plugin JWT per iniziare rapidamente:
Oppure puoi usare quelli suggeriti nella documentazione:

Ho bisogno dell'ID utente se l'utente è loggato nel sito. Poiché l'endpoint è aperto, non è necessario verificare i permessi.

Questa riga restituisce sempre false anche se l'utente è loggato nel sito web.
$rs['wp_get_current_user'] = is_user_logged_in() ? get_current_user_id() : false;

Ciao @ShahAlom, come ho menzionato nella mia risposta, essere loggati nel sito web non è la stessa cosa che essere loggati nell'API REST, ti consiglio di dare un'occhiata ai metodi di autenticazione dell'API REST nella documentazione: https://developer.wordpress.org/rest-api/using-the-rest-api/authentication/

Per l'autenticazione tramite cookie: per gli sviluppatori che effettuano richieste Ajax manuali, il nonce dovrà essere passato con ogni richiesta. L'API utilizza nonce con l'azione impostata su wp_rest. Questi possono poi essere passati all'API tramite il parametro dati _wpnonce (sia nei dati POST che nella query per le richieste GET), o tramite l'header X-WP-Nonce. Se non viene fornito alcun nonce, l'API imposterà l'utente corrente a 0, trasformando la richiesta in una richiesta non autenticata, anche se si è loggati in WordPress.

Per favore aggiorna la tua risposta con questo ultimo commento così che io possa accettarla come soluzione.

Anche con l'autenticazione JWT, è comunque necessario passare l'header X-WP-Nonce per ottenere l'utente corrente, ad esempio se hai bisogno di accedere a users/me restituisce comunque 401, lo stesso per query users by role, e così via. Le richieste AJAX "non manuali" sono "speciali" solo perché il client API ufficiale include quell'header, ma nient'altro.

@JesúsFranco dalla mia esperienza usando il plugin JWT, non è necessario inviare alcun header aggiuntivo, basta l'header Authorization con il token generato precedentemente per l'autenticazione, /wp-v2/users/me
funziona per me

Hmmm, questo mi fa pensare a cosa potrebbe essere diverso da setup a setup, la versione del plugin? Del core?

Riflettendo su quali potrebbero essere le differenze, ho osservato due tipi di richieste che vengono proibite senza l'uso del nonce, e permesse senza di esso, allo stesso modo. La differenza che ho notato è l'ambiente della richiesta. Le richieste attraverso uno script PHP sono permesse con il solo Token sufficiente, le richieste attraverso il browser no senza il nonce.

@JesúsFranco hai ragione, per le richieste lato server (nel mio caso), il token sarà sufficiente, per chiamate AJAX lato client/manuali, devi includere il nonce per evitare CSRF, non c'è bisogno di includere il token dato che hai già un utente loggato e il lato client è basato sui cookie

Se una chiamata API arriva senza un nonce impostato, WordPress deautenticherà la richiesta, terminando l'utente corrente e rendendo la richiesta non autenticata. Questa protezione CSFR è automatica e non devi fare nulla per farla funzionare oltre a includere il nonce.
Il modo per risolvere questo problema è includere un nonce. Qualcosa come questo:
$_wpnonce = wp_create_nonce( 'wp_rest' );
echo "<input type = 'hidden' name = '_wpnonce' value = '$_wpnonce' />";
E includerlo nella tua richiesta API. Il nonce deve essere chiamato "_wpnonce" e l'azione deve essere "wp_rest" per far funzionare l'API. Può essere inserito nell'URL o nel corpo del post.

Per avere un esempio di codice completamente funzionante, ecco un plugin di esempio su come recuperare l'ID dell'utente corrente via REST.
my-plugin.php
class MyPlugin {
public function __construct() {
add_action('wp_enqueue_scripts', [$this, 'scripts']);
add_action('rest_api_init', [$this, 'rest']);
}
function scripts() {
// Aggiunge JS.
wp_enqueue_script('my-plugin', plugin_dir_url(__FILE__) . 'js/scripts.js', ['jquery'], NULL, TRUE);
// Passa il nonce al JS.
wp_localize_script('my-plugin', 'MyPluginSettings', [
'nonce' => wp_create_nonce('wp_rest'),
]);
}
function rest() {
// Registra la rotta.
register_rest_route('my-plugin/v1', '/uid', [
'methods' => WP_REST_Server::READABLE,
'callback' => [$this, 'rest_callback'],
]);
}
function rest_callback($data) {
// Ottieni l'ID dell'utente corrente.
$data = [
'uid' => get_current_user_id(),
];
$response = new WP_REST_Response($data, 200);
// Imposta gli header.
$response->set_headers(['Cache-Control' => 'must-revalidate, no-cache, no-store, private']);
return $response;
}
}
new MyPlugin();
js/scripts.js
(function($) {
$(document).ready(function() {
var settings = MyPluginSettings;
$.ajax({
url: '/wp-json/my-plugin/v1/uid',
method: 'GET',
beforeSend: function(xhr) {
xhr.setRequestHeader('X-WP-Nonce', settings.nonce);
}
}).done(function(response) {
// Restituirà il tuo UID.
console.log(response);
});
});
})(jQuery);
Risorsa: https://developer.wordpress.org/rest-api/using-the-rest-api/authentication/

Non capisco come 'MyPluginSettings' venga passato allo script. Cose da considerare: attualmente non sto usando JQuery ma JavaScript "vanilla" ... stavo inserendo il mio script nei tag html <script> quando necessario, ma ho provato a includerli con wp_enqueue_script e ho avuto lo stesso problema.

Ho risolto il problema, avevo scritto un percorso errato quando ho adattato per wp_enqueue_script(). Inoltre, avevo più script e ho appena capito che il primo parametro di wp_enqueue_script() non è specifico del plug-in ma è specifico dello script (forse dovresti cambiare 'my-plugin' nella tua risposta perché può creare confusione).

wp_get_current_user()
non funziona perché il tuo utente non è impostato correttamente. Vedi il codice qui sotto in /wp-includes/user.php
per riferimento.
if ( ! empty( $current_user ) ) {
if ( $current_user instanceof WP_User ) {
return $current_user;
}
// Aggiorna stdClass a WP_User
if ( is_object( $current_user ) && isset( $current_user->ID ) ) {
$cur_id = $current_user->ID;
$current_user = null;
wp_set_current_user( $cur_id );
return $current_user;
}
// $current_user ha un valore non valido. Forza a WP_User con ID 0.
$current_user = null;
wp_set_current_user( 0 );
return $current_user;
}
if ( defined( 'XMLRPC_REQUEST' ) && XMLRPC_REQUEST ) {
wp_set_current_user( 0 );
return $current_user;
}
Tutto quello che devi fare è chiamare wp_set_current_user( {user_id} ) all'inizio della tua API.
