Ich versuche zu verwenden Cookie-Authentifizierung für den Zugriff auf die WordPress-REST-API mithilfe der API abrufendie Authentifizierung schlägt jedoch mit dem folgenden Fehler fehl.
403: Cookie Nonce ist ungültig
Ich verwende das folgende Skript, um eine Verbindung zur API herzustellen.
const headers = new Headers({
'Content-Type': 'application/json',
'X-WP-Nonce': WPAPI.nonce
});
fetch(WPAPI.root + 'my-endpoint/upload/', {
method: 'POST',
headers: headers,
body: JSON.stringify(data)
})
Wenn ich von der Verwendung von Fetch zu wechsle XMLHttpRequest es funktioniert wie erwartet.
let request = new XMLHttpRequest();
request.open('POST', WPAPI.root + 'my-endpoint/upload/', true);
request.setRequestHeader('X-WP-Nonce', WPAPI.nonce);
request.setRequestHeader('Content-Type', 'application/json');
request.send(JSON.stringify(data));
Gibt es möglicherweise ein Problem mit der Art und Weise, wie Header in der Fetch-Methode gesendet werden?
Die WordPress-Nonce-Authentifizierung erfordert die Verwendung von Cookies und standardmäßig sendet Fetch diese nicht mit. Sie können die Option “Anmeldeinformationen” verwenden, damit dies funktioniert:
fetch(endpoint, {
credentials: 'same-origin'
})
https://github.com/github/fetch#sending-cookies
Bin auf meinen Beitrag von vor 4 Jahren gestoßen, auf der Suche nach dem gleichen Problem 🙂 Dies löst das Problem.
const response = await fetch(url, {
method: 'POST',
credentials: 'same-origin',
headers: {
'Content-Type': 'application/json',
'X-WP-Nonce' : my_var.nonce
},
body: JSON.stringify(data),
});
const content = await response.json();
console.log(content);
Spät, aber vielleicht hilfreich für andere Leser, da ich Code speziell für hinzugefügt habe bringen() Versprechen nach dieser Frage.
WordPress verwendet einmal automatisch in ihren Cookies, wie ich herausgefunden habe.
Lösung: Berechtigungs-Callback-Funktion prüft auf Cookie
WordPress: Version 5.7.2
PHP: Version 7.4
Gastgeber: hostmonster.com
Klient: Windows 10
Browser: getestet auf Chrome, Firefox, sogar Edge 😜 hat funktioniert
Code (PHP Code in der function.php Ihres installierten Themes):
add_action('rest_api_init', function() {
/**
* Register here your custom routes for your CRUD functions
*/
register_rest_route( 'my-endpoint/v1', '/upload/', array(
array(
'methods' => WP_REST_Server::READABLE, // = 'GET'
'callback' => 'get_data',
// Always allow, as an example
'permission_callback' => '__return_true'
),
array(
'methods' => WP_REST_Server::CREATABLE, // = 'POST'
'callback' => 'create_data',
// Here we register our permissions callback
// The callback is fired before the main callback to check if the current user can access the endpoint
'permission_callback' => 'prefix_get_private_data_permissions_check',
),
));
});
// The missing part:
// Add your Permission Callback function here, that checks for the cookie
// You should define your own 'prefix_' name, though
function prefix_get_private_data_permissions_check() {
// Option 1: Password Protected post or page:
// Restrict endpoint to browsers that have the wp-postpass_ cookie.
if ( !isset($_COOKIE['wp-postpass_'. COOKIEHASH] )) {
return new WP_Error( 'rest_forbidden', esc_html__( 'OMG you can not create or edit private data.', 'my-text-domain' ), array( 'status' => 401 ) );
};
// Option 2: Authentication based on logged-in user:
// Restrict endpoint to only users who have the edit_posts capability.
if ( ! current_user_can( 'edit_posts' ) ) {
return new WP_Error( 'rest_forbidden', esc_html__( 'OMG you can not create or edit private data.', 'my-text-domain' ), array( 'status' => 401 ) );
};
// This is a black-listing approach. You could alternatively do this via white-listing, by returning false here and changing the permissions check.
return true;
};
function create_data() {
global $wpdb;
$result = $wpdb->query(...);
return $result;
}
function get_data() {
global $wpdb;
$data = $wpdb->get_results('SELECT * from `data`');
return $data;
}
Stellen Sie sicher, dass Sie es in Ihre HTML-Seite aufnehmen credentials: 'same-origin'
in Ihrer HTTP-Anforderung, wie in den vorherigen Antworten und Kommentaren oben richtig angegeben.
Code (HTML mit Inline <script> ... </script>
):
<script>
// Here comes the REST API part:
// HTTP requests with fetch() promises
function getYourData() {
let url="https://example.com/wp-json/my-endpoint/v1/upload/";
fetch(url, {
method: 'GET',
credentials: 'same-origin', // <-- make sure to include credentials
headers:{
'Content-Type': 'application/json',
'Accept': 'application/json',
//'Authorization': 'Bearer ' + token <-- not needed, WP does not check for it
}
}).then(res => res.json())
.then(response => get_success(response))
.catch(error => failure(error));
};
function insertYourData(data) {
let url="https://example.com/wp-json/my-endpoint/v1/upload/";
fetch(url, {
method: 'POST',
credentials: 'same-origin', // <-- make sure to include credentials
headers:{
'Content-Type': 'application/json',
'Accept': 'application/json',
//'Authorization': 'Bearer ' + token <-- not needed, WP does not check for it
},
body: JSON.stringify(data)
}).then(res => res.json())
.then(response => create_success(response))
.catch(error => failure(error));
};
// your Success and Failure-functions:
function get_success(json) {
// do something here with your returned data ....
console.log(json);
};
function create_success(json) {
// do something here with your returned data ....
console.log(json);
};
function failure(error) {
// do something here ....
console.log("Error: " + error);
};
</script>
Abschließende Gedanken:
Ist 'Authorization': 'Bearer ' + token
notwendig im Header der HTTP-Anfrage?
Nach einigem Testen wurde mir das klar if ( !isset($_COOKIE['wp-postpass_'. COOKIEHASH] )) { ...
innerhalb der Berechtigungsrückruf prüft nicht nur, ob das Cookie im Client-Browser gesetzt ist, aber es scheint auch seinen Wert zu überprüfen (das JWT-Token).
Weil ich wie bei meinem ursprünglichen Code doppelt überprüft habe, ein falsches Token übergebe, das Cookie lösche oder die Sitzung offen lasse, aber im Back-End das Passwort der Website ändere (daher würde WordPress ein neues Token erstellen, daher der Wert set wp_postpass_
Cookie würde sich ändern) und alle Tests verliefen korrekt – REST-API blockiert, wodurch nicht nur das Vorhandensein eines Cookies, sondern auch sein Wert überprüft wird (was gut ist – danke WordPress-Team).
Quellen:
Ich habe die folgende Ressource zu den obigen Gedanken in der gefunden FAQ-Bereich:
Warum überprüft die REST-API den eingehenden Origin-Header nicht? Setzt dies meine Website CSRF-Angriffen aus?
Da die WordPress-REST-API den Origin-Header eingehender Anfragen nicht überprüft, kann daher von jeder Seite aus auf öffentliche REST-API-Endpunkte zugegriffen werden. Dies ist eine bewusste Designentscheidung.
WordPress verfügt jedoch über einen bestehenden CSRF-Schutzmechanismus, der Nonces verwendet.
Und nach meinen bisherigen Tests Die WP-Authentifizierung funktioniert einwandfrei.
Daumen hoch 👍 für das WordPress-Team
Zusätzliche 2 Quellen aus dem WordPress REST-API-Handbuch:
REST-API-Handbuch / Erweiterung der REST-API / Routen und Endpunkte
REST-API-Handbuch / Erweitern der REST-API / Hinzufügen benutzerdefinierter Endpunkte
Und 1 Quelle aus WordPress Code-Referenz betreffend rest_cookie_check_errors()
Funktion:
Referenz / Funktionen / rest_cookie_check_errors()
Für diejenigen, die an der vollständigen Geschichte meiner Ergebnisse interessiert sind, folgen Sie dem Link zu meinem Thread mit Antworten, Code-Snippets und zusätzlichen Ergebnissen.
So erzwingen Sie die Authentifizierung auf der REST-API für eine passwortgeschützte Seite mit einer benutzerdefinierten Tabelle und fetch() ohne Plugin