Die Funktion wp_get_current_user () funktioniert nicht in der Rückruffunktion der Rest-API


8

Betrachten Sie die folgende Klasse.

<?php
class MCQAcademy_Endpoint extends WP_REST_Controller {

    /**
     * Register the routes for the objects of the 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(),
                )
            )
        );
    }

    /**
     *
     */
    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(); // Does not output as expected

        return new WP_REST_Response( $rs, 200 );
    }

    /**
     * Check if a given request has access to get items
     */
    public function get_items_permissions_check( $request ) {
        return true; // to make readable by all
    }


    /**
     * Prepare the item for create or update operation
     */
    protected function prepare_item_for_database( $request ) {
        return $request;
    }

    /**
     * Prepare the item for the REST response
     */
    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;
    }

    /**
     * Get the query params for collections
     */
    public function get_collection_params() {
        return array(
            'page'     => array(
                'description'        => 'Current page of the collection.',
                'type'               => 'integer',
                'default'            => 1,
                'sanitize_callback'  => 'absint',
            ),
            'per_page' => array(
                'description'        => 'Maximum number of items to be returned in result set.',
                'type'               => 'integer',
                'default'            => 10,
                'sanitize_callback'  => 'absint',
            ),
            'search'   => array(
                'description'        => 'Limit results to those matching a string.',
                'type'               => 'string',
                'sanitize_callback'  => 'sanitize_text_field',
            ),
        );
    }

    // Register our REST Server
    public function hook_rest_server(){
        add_action( 'rest_api_init', array( $this, 'register_routes' ) );
    }
}

$myEndpoint = new MCQAcademy_Endpoint();
$myEndpoint->hook_rest_server();

Alles läuft gut, außer dass der Aufruf der wp_get_current_user()Funktion in der get_items()Funktion einen leeren Benutzer zurückgibt, obwohl sich der Benutzer logged inauf der Website befindet.

Antworten:


10

Auf Ihrer Website angemeldet bedeutet nicht, dass der Benutzer in der REST-API-Anforderung authentifiziert ist. Aus diesem Grund erhalten Sie nicht den richtigen Benutzer oder einen Id = 0

Bitte sehen Sie sich die REST-API-Authentifizierungsmethoden in den Dokumenten an:
https://developer.wordpress.org/rest-api/using-the-rest-api/authentication/

Für Entwickler, die manuelle Ajax-Anfragen stellen, muss die Nonce bei jeder Anfrage übergeben werden. Die API verwendet Nonces mit der Aktion wp_rest. Diese können dann über den Datenparameter _wpnonce (entweder POST-Daten oder in der Abfrage nach GET-Anforderungen) oder über den X-WP-Nonce-Header an die API übergeben werden. Wenn keine Nonce angegeben ist, setzt die API den aktuellen Benutzer auf 0 und verwandelt die Anforderung in eine nicht authentifizierte Anforderung, selbst wenn Sie bei WordPress angemeldet sind.

Für die Remote-Authentifizierung würde ich das JWT-Plugin für einen schnellen Start empfehlen:
https://es.wordpress.org/plugins/jwt-authentication-for-wp-rest-api/

Oder Sie können die in den Dokumenten vorgeschlagenen verwenden:
https://developer.wordpress.org/rest-api/using-the-rest-api/authentication/#authentication-plugins


1
Ich benötige eine Benutzer-ID, wenn der Benutzer auf der Site angemeldet ist. Da der Endpunkt geöffnet ist, muss die Berechtigung nicht überprüft werden.
— Shah Alom

Diese Zeile gibt immer false zurück, obwohl der Benutzer auf der Website angemeldet ist. $rs['wp_get_current_user'] = is_user_logged_in() ? get_current_user_id() : false;
— Shah Alom

2
Für die Cookie-Authentifizierung: Für Entwickler, die manuelle Ajax-Anforderungen stellen, muss das Nonce bei jeder Anforderung übergeben werden. Die API verwendet Nonces mit der Aktion wp_rest. Diese können dann über den Datenparameter _wpnonce (entweder POST-Daten oder in der Abfrage nach GET-Anforderungen) oder über den X-WP-Nonce-Header an die API übergeben werden. Wenn keine Nonce angegeben ist, setzt die API den aktuellen Benutzer auf 0 und verwandelt die Anforderung in eine nicht authentifizierte Anforderung, selbst wenn Sie bei WordPress angemeldet sind.
— Pabamato

1
Selbst bei der JWT-Authentifizierung müssen Sie den X-WP-Nonce-Header noch übergeben, um den aktuellen Benutzer abzurufen. Wenn Sie beispielsweise auf Benutzer zugreifen müssen, gibt me / me weiterhin 401 zurück, dies gilt auch für Abfragebenutzer nach Rolle usw. Die "nicht manuellen" AJAX-Anforderungen sind "speziell", nur weil der offizielle API-Client diesen Header enthält, aber sonst nichts.
— Jesús Franco

2
@ JesúsFranco Sie haben Recht, für serverseitige Anfragen (mein Fall) wird das Token ausreichen, für clientseitige / manuelle Ajax-Aufrufe müssen Sie das Nonce einschließen, um CSRF zu vermeiden. Es ist nicht erforderlich, das Token einzuschließen, da Sie dies bereits tun habe einen angemeldeten Benutzer und Client-Seite ist Cookie-basiert
— Pabamato

1

Um ein voll funktionsfähiges Codebeispiel zu erhalten, finden Sie hier ein Beispiel-Plugin zum Abrufen der aktuellen Benutzer-ID über 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() {

    // Add JS.
    wp_enqueue_script('my-plugin', plugin_dir_url(__FILE__) . 'js/scripts.js', ['jquery'], NULL, TRUE);
    // Pass nonce to JS.
    wp_localize_script('my-plugin', 'MyPluginSettings', [
      'nonce' => wp_create_nonce('wp_rest'),
    ]);
  }

  function rest() {

    // Register route.
    register_rest_route('my-plugin/v1', '/uid', [
      'methods'  => WP_REST_Server::READABLE,
      'callback' => [$this, 'rest_callback'],
    ]);
  }

  function rest_callback($data) {

    // Get current user ID.
    $data = [
      'uid' => get_current_user_id(),
    ];

    $response = new WP_REST_Response($data, 200);
    // Set headers.
    $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) {

      // Will return your UID.
      console.log(response);
    });

  });

})(jQuery);

Ressource: https://developer.wordpress.org/rest-api/using-the-rest-api/authentication/


Ich verstehe nicht, wie 'MyPluginSettings' an das Skript übergeben wird. Mögliche Dinge zu beachten: Ich verwende derzeit nicht JQuery, sondern "Vanille" JavaScript ... Ich habe mein Skript bei Bedarf in HTML-Tags <script> eingefügt, aber ich habe versucht, sie in wp_enqueue_script aufzunehmen, und habe das gleiche Problem festgestellt.
— TTT

1
Ich habe das zum Laufen gebracht, ich hatte einen falschen Pfad geschrieben, als ich mich für wp_enqueue_script () angepasst habe. Aber ich hatte auch mehrere Skripte und ich habe gerade verstanden, dass der erste Parameter von wp_enqueue_script () nicht spezifisch für das Plug-In ist, sondern spezifisch für das Skript (vielleicht sollten Sie 'my-plugin' in Ihrer Antwort ändern, weil das verwirrend ist .
— TTT

@TTT - Tauschen Sie es my-scriptzum Beispiel mit? Ja, es sollte nur ein eindeutiger Handle-Name sein, der häufig den Namen des Plugins oder Themas enthält.
— Leymannx

1

wp_get_current_user()funktioniert nicht, weil Ihr Benutzer nicht perfekt eingestellt ist. Siehe unten stehenden Code /wp-includes/user.phpals Referenz.

if ( ! empty( $current_user ) ) {
    if ( $current_user instanceof WP_User ) {
        return $current_user;
    }

    // Upgrade stdClass to 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 has a junk value. Force to WP_User with 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;
}

Sie müssen lediglich wp_set_current_user ({user_id}) am Anfang Ihrer API verwenden.


0

Wenn ein API-Aufruf eingeht, für den kein Nonce festgelegt ist, wird die Anforderung von WordPress de-authentifiziert, wodurch der aktuelle Benutzer beendet und die Anforderung nicht authentifiziert wird. Dieser CSFR-Schutz erfolgt automatisch, und Sie müssen nichts tun, damit er funktioniert, außer das Nonce einzuschließen.

Der Weg, dies zu lösen, besteht darin, eine Nonce einzuschließen. Etwas wie das:

$_wpnonce = wp_create_nonce( 'wp_rest' );
echo "<input type = 'hidden' name = '_wpnonce' value = '$_wpnonce' />";

Und nehmen Sie es in Ihre API-Anfrage auf. Die Nonce muss "_wpnonce" heißen und die Aktion muss "wp_rest" sein, damit die API funktioniert. Es kann in die URL oder in den Post-Body gehen.

Durch die Nutzung unserer Website bestätigen Sie, dass Sie unsere Cookie-Richtlinie und Datenschutzrichtlinie gelesen und verstanden haben.
Licensed under cc by-sa 3.0 with attribution required.