---
title: "REST-API von WordPress absichern: Gastzugriffe einschränken, Formulare und Editor erhalten"
date: 2026-09-30T21:20:31+02:00
modified: 2026-11-10T17:19:33+01:00
category: wordpress
type: how_to
author: Marcel Schönfelder
canonical: https://s-edv.com/anleitungen/wordpress-rest-api-absichern-endpunkte-einschraenken
keywords:
  - WordPress
  - Sicherheit
  - REST-API
  - Anwendungspasswörter
  - Must-Use-Plugin
reading_time: 8
---

# REST-API von WordPress absichern: Gastzugriffe einschränken, Formulare und Editor erhalten

Die REST-API ist heute das Rückgrat von WordPress: Der Block-Editor, viele Formular-Plugins und externe Apps sprechen über `/wp-json/` mit der Website. In der Grundeinstellung beantwortet sie auch Anfragen von Gästen, liefert öffentliche Beiträge, Seiten und eine Liste aller Routen. Schreibende Zugriffe sind ohne Anmeldung zwar gesperrt, dennoch lohnt es sich, die Angriffsfläche zu verkleinern. Diese Anleitung zeigt, was die REST-API ohne Anmeldung preisgibt, wie Sie sie mit einer Freigabeliste auf angemeldete Benutzer beschränken, ohne Formulare und Einbettungen zu zerstören, und wie externe Dienste über Anwendungspasswörter sicher zugreifen.

**Kurzfassung:** Die REST-API ganz abzuschalten, zerstört den Block-Editor. Beschränken Sie stattdessen Gastzugriffe mit dem Filter `rest_authentication_errors` in einem Must-Use-Plugin und geben Sie nur die Namensräume frei, die Besucher brauchen, etwa oEmbed und Ihr Formular-Plugin. Angemeldete Benutzer und der Editor arbeiten weiter, externe Dienste melden sich mit Anwendungspasswörtern an. Testen Sie jede Freigabe mit `curl`, bevor Sie die Regel produktiv setzen.

## Voraussetzungen

- [ ] **WordPress:** Anwendungspasswörter gibt es seit WordPress 5.6.
- [ ] **PHP:** PHP 8.0 oder neuer für das Beispiel, weil es `str_starts_with()` nutzt.
- [ ] **HTTPS:** Anwendungspasswörter stehen nur über HTTPS zur Verfügung, außer in einer lokalen Entwicklungsumgebung. In der Umgebung „production“ meldet `wp_is_application_passwords_available()` ohne HTTPS `false`.
- [ ] **Zugriff:** Backend mit der Rolle Administrator, Dateizugriff per SFTP oder SSH, optional WP-CLI.
- [ ] **Permalinks:** Die Beispiele nutzen `/wp-json/`. Bei der Einstellung „Einfach“ unter Einstellungen > Permalinks lautet der Pfad `/?rest_route=/`.
- [ ] **Backup:** eine aktuelle Sicherung. Eine fehlerhafte Regel kann Editor oder Formulare lahmlegen.

## Schritt 1: Bestandsaufnahme der öffentlichen REST-API

Rufen Sie zuerst den Index der API ohne Anmeldung ab. Er listet alle Namensräume, also die Bereiche, die WordPress und Plugins registriert haben:

```bash
$ curl -s https://www.example.de/wp-json/ | python3 -c "import sys,json; j=json.load(sys.stdin); print(len(j['routes']), j['namespaces'])"
```

Mit Contact Form 7 lautet die Ausgabe sinngemäß: 139 Routen in den Namensräumen `oembed/1.0`, `contact-form-7/v1`, `wp/v2`, `wp-site-health/v1`, `wp-block-editor/v1` und `wp-abilities/v1`. Jede Route prüft selbst, ob der Aufrufer berechtigt ist. Ohne Anmeldung liefert `/wp/v2/posts` veröffentlichte Beiträge, `/wp/v2/settings` antwortet mit `rest_forbidden` und Status 401, ein POST auf `/wp/v2/posts` mit `rest_cannot_create`. Die Grundeinstellung ist also nicht offen für Schreibzugriffe. Das Risiko liegt bei Plugins, deren Routen die Berechtigung fehlerhaft prüfen, und bei Informationen wie Benutzerlisten.

Notieren Sie, welche Namensräume Besucher ohne Anmeldung wirklich brauchen. Typisch sind `oembed/1.0` für das Einbetten Ihrer Beiträge auf anderen Websites und der Namensraum des Formular-Plugins, weil viele Formulare per JavaScript an die REST-API senden.

> **Prüfen:** Sie haben eine Liste der Namensräume und wissen für jeden, ob Gäste ihn benötigen.

## Schritt 2: Entscheiden, was eingeschränkt wird

Es gibt drei Stufen, die sich in Aufwand und Nebenwirkungen unterscheiden:

| Stufe | Wirkung | Nebenwirkung |
| --- | --- | --- |
| Einzelne Routen entfernen (`rest_endpoints`) | nur bestimmte Routen verschwinden, etwa Benutzer | gering, gilt aber auch für angemeldete Benutzer, wenn nicht unterschieden |
| Gäste mit Freigabeliste sperren (`rest_authentication_errors`) | Gäste erreichen nur freigegebene Namensräume | Freigaben müssen gepflegt werden, wenn Plugins dazukommen |
| REST-API ganz abschalten | keine Antworten mehr | Block-Editor, viele Plugins und Apps funktionieren nicht mehr |

Die dritte Stufe scheidet für praktisch jede aktuelle Website aus. Für Unternehmenswebsites, die keine öffentliche API anbieten, ist die zweite Stufe ein guter Kompromiss. Die gezielte Sperre der Benutzer-Routen beschreibt die Anleitung [Benutzer-Enumeration in WordPress verhindern](https://s-edv.com/anleitungen/wordpress-benutzer-enumeration-autorenarchive-schuetzen). Diese Anleitung setzt die zweite Stufe um.

> **Prüfen:** Die gewählte Stufe passt zu Ihren Diensten. Wenn eine Headless-Frontend-Anwendung oder eine App öffentlich Inhalte über die REST-API lädt, gehört deren Namensraum auf die Freigabeliste.

## Schritt 3: Must-Use-Plugin mit Freigabeliste anlegen

Der Filter `rest_authentication_errors` läuft bei jeder REST-Anfrage, bevor eine Route ausgeführt wird. Gibt er einen Fehler zurück, bricht WordPress die Anfrage ab. Legen Sie die Datei `wp-content/mu-plugins/rest-schutz.php` an:

Datei: `wp-content/mu-plugins/rest-schutz.php`

```php
<?php
/**
 * Plugin Name: REST-API einschränken
 */
defined( 'ABSPATH' ) || exit;

add_filter( 'rest_authentication_errors', function ( $result ) {
	// Ergebnis anderer Prüfungen nicht überschreiben.
	if ( true === $result || is_wp_error( $result ) ) {
		return $result;
	}
	if ( is_user_logged_in() ) {
		return $result;
	}
	// Namensräume, die Gäste erreichen dürfen.
	$frei  = array( '/oembed/1.0', '/contact-form-7/v1' );
	$route = untrailingslashit( $GLOBALS['wp']->query_vars['rest_route'] ?? '' );
	foreach ( $frei as $prefix ) {
		if ( str_starts_with( $route, $prefix ) ) {
			return $result;
		}
	}
	return new WP_Error( 'rest_not_logged_in', 'Anmeldung erforderlich.', array( 'status' => 401 ) );
} );
```

Warum so aufgebaut: Die erste Prüfung reicht Ergebnisse anderer Authentifizierungen unverändert durch, wie es die Entwicklerdokumentation für diesen Filter empfiehlt. Die Prüfung `is_user_logged_in()` lässt angemeldete Benutzer durch, das umfasst die Anmeldung per Cookie mit gültigem Nonce und per Anwendungspasswort. Die Route lesen Sie aus der Abfragevariable `rest_route`, die WordPress sowohl bei `/wp-json/` als auch bei `?rest_route=` setzt. Passen Sie die Liste `$frei` an Ihre Plugins an. Die Funktion `str_starts_with()` gibt es erst ab PHP 8.0.

> **Prüfen:** `php -l wp-content/mu-plugins/rest-schutz.php` meldet `No syntax errors detected`, und die Startseite lädt mit Status 200.

## Schritt 4: Sperre und Freigaben testen

Testen Sie jetzt ohne Anmeldung, jeweils mit Ihrer Adresse:

```bash
$ curl -s https://www.example.de/wp-json/
$ curl -s https://www.example.de/wp-json/wp/v2/posts
$ curl -s "https://www.example.de/?rest_route=/wp/v2/users"
$ curl -s -o /dev/null -w "%{http_code}\n" "https://www.example.de/wp-json/oembed/1.0/embed?url=https://www.example.de/ein-beitrag/"
```

Die ersten drei Aufrufe liefern:

```plaintext
{"code":"rest_not_logged_in","message":"Anmeldung erforderlich.","data":{"status":401}}
```

Der oEmbed-Aufruf antwortet mit `200`. Senden Sie zusätzlich ein Testformular über die Website. Der Endpunkt von Contact Form 7 nimmt die Formulardaten trotz Sperre an und antwortet bei fehlgeschlagenem Mailversand mit `"status":"mail_failed"`. Entscheidend ist, dass keine 401-Antwort kommt. Auf einer echten Website erscheint die Bestätigungsmeldung des Formulars.

> **Prüfen:** Gesperrte Routen liefern `rest_not_logged_in` mit Status 401, freigegebene Namensräume antworten normal, und Kontaktformulare lassen sich absenden.

## Schritt 5: Editor und angemeldete Zugriffe prüfen

Öffnen Sie im Backend einen Beitrag im Block-Editor, ändern Sie etwas und speichern Sie. Der Editor sendet bei jeder Anfrage ein Nonce im Header `X-WP-Nonce` mit. WordPress wertet das Anmelde-Cookie in der REST-API nur zusammen mit diesem Nonce aus, als Schutz gegen Cross-Site-Request-Forgery. Dabei liefert `/wp/v2/users/me` mit Cookie und Nonce Status 200. Mit Cookie, aber ohne Nonce kommt dagegen der Fehlercode `rest_not_logged_in` mit Status 401, und zwar mit der Standardmeldung von WordPress statt der Meldung aus der eigenen Regel. Das ist gewollt und kein Fehler der Regel.

> **Prüfen:** Speichern im Block-Editor funktioniert, Medien lassen sich hochladen, und die Browserkonsole zeigt keine Antworten mit Status 401 von `/wp-json/`.

## Schritt 6: Externe Dienste mit Anwendungspasswörtern anbinden

Dienste, die von außen auf die REST-API zugreifen, etwa ein Warenwirtschaftssystem oder ein Automatisierungswerkzeug, melden sich mit einem Anwendungspasswort an. Es wird pro Dienst vergeben, lässt sich einzeln widerrufen und berechtigt nicht zur Anmeldung im Backend. Legen Sie es unter **Benutzer > Profil** im Abschnitt „Anwendungspasswörter“ an: Tragen Sie unter „Name des neuen Anwendungspassworts“ den Dienst ein und klicken Sie auf „Anwendungspasswort hinzufügen“. Per WP-CLI geht es so:

```bash
$ wp user application-password create dienst-konto warenwirtschaft --porcelain
```

WordPress zeigt das Passwort nur einmal. Legen Sie für jeden Dienst ein eigenes Konto mit der kleinsten passenden Rolle an, nicht Ihr Administratorkonto. Der Dienst sendet Kontoname und Anwendungspasswort per HTTP Basic Auth:

```bash
$ curl -s -u "dienst-konto:xxxx xxxx xxxx xxxx xxxx xxxx" https://www.example.de/wp-json/wp/v2/users/me
```

Ein gültiges Anwendungspasswort liefert trotz Sperre Status 200, ein falsches Passwort die Antwort `rest_not_logged_in`. Widerrufen Sie Passwörter für Dienste, die Sie nicht mehr nutzen, im selben Abschnitt des Profils.

Jedes neue Plugin mit eigenem Namensraum ist ein Anlass, die Freigabeliste zu prüfen. Solche Kontrollen gehören zur laufenden Pflege wie Updates und Backups. Wer das nicht selbst im Kalender halten möchte, kann es abgeben: Die [WordPress-Wartung von wordpressupdate.de](https://wordpressupdate.de/?utm_source=s-edv.com&utm_medium=artikel&utm_campaign=40) übernimmt Updates mit Kompatibilitätsprüfung, wöchentliche Backups auf externen Speicher und die Wartung der Firewall.

> **Prüfen:** Der externe Dienst arbeitet mit seinem Anwendungspasswort, und `wp user application-password list dienst-konto` zeigt nur Passwörter, die Sie zuordnen können.

## Typische Fehler

**Kontaktformular hängt oder meldet einen Fehler**

Der Namensraum des Formular-Plugins fehlt in `$frei`. Ermitteln Sie ihn im Browser über die Entwicklerwerkzeuge im Reiter „Netzwerk“ beim Absenden und ergänzen Sie ihn.

**Abschnitt „Anwendungspasswörter“ fehlt im Profil**

Die Website läuft ohne HTTPS, oder ein Plugin hat die Funktion abgeschaltet. Stellen Sie auf HTTPS um.

**Externer Dienst erhält trotz korrektem Passwort 401**

Manche Server geben den Header `Authorization` nicht an PHP weiter. Die Standard-`.htaccess` von WordPress enthält dafür eine Regel mit `HTTP_AUTHORIZATION`. Prüfen Sie, ob sie vorhanden ist und `mod_rewrite` läuft.

**`/wp-json/` liefert die Startseite statt JSON**

Die Permalinks stehen auf „Einfach“. Nutzen Sie `/?rest_route=/` oder stellen Sie die Permalinks um. Genau das tritt vor der Umstellung auf.

**Kritischer Fehler nach dem Hochladen**

PHP älter als 8.0 kennt `str_starts_with()` nicht. Aktualisieren Sie PHP oder ersetzen Sie die Prüfung durch `0 === strpos( $route, $prefix )`.

## Häufige Fragen

### Reicht es nicht, die REST-API mit einem Plugin abzuschalten?

Eine vollständige Abschaltung legt den Block-Editor lahm, weil er selbst über die REST-API arbeitet. Brauchbare Plugins müssen deshalb ebenfalls Ausnahmen für angemeldete Benutzer machen. Eine eigene Regel mit wenigen Zeilen ist nachvollziehbar, und Sie wissen genau, welche Namensräume offen sind.

### Ist die Sperre für Suchmaschinen ein Problem?

Nein. Suchmaschinen lesen die HTML-Seiten und die Sitemap, nicht die REST-API. Der Link-Header mit der API-Adresse bleibt bestehen, führt Gäste aber nur zur Fehlermeldung.

### Schützt das vor Lücken in Plugins?

Teilweise. Lücken in REST-Routen eines Plugins sind für Gäste nicht mehr erreichbar, solange der Namensraum nicht freigegeben ist. Lücken im freigegebenen Formular-Plugin oder außerhalb der REST-API bleiben bestehen. Updates sind weiterhin der wichtigste Schutz.

## Fazit

Eine Freigabeliste im Filter `rest_authentication_errors` verkleinert die öffentliche REST-API auf das, was Besucher brauchen, während Editor und angemeldete Dienste normal weiterarbeiten. Die Pflege der Liste gehört zu jedem neuen Plugin dazu. Wer diese Pflege zusammen mit Updates und Backups abgeben möchte, findet das bei der [WordPress-Wartung von Marcel Schönfelder](https://wordpressupdate.de/?utm_source=s-edv.com&utm_medium=fazit&utm_campaign=40).

## Weiterführende Anleitungen und Quellen

- [Benutzer-Enumeration in WordPress verhindern](https://s-edv.com/anleitungen/wordpress-benutzer-enumeration-autorenarchive-schuetzen)
- [XML-RPC in WordPress deaktivieren oder einschränken](https://s-edv.com/anleitungen/wordpress-xml-rpc-deaktivieren-einschraenken)
- [WordPress-Sicherheitsheader setzen](https://s-edv.com/anleitungen/wordpress-sicherheitsheader-csp-hsts-x-frame-options)
- [REST-API-Handbuch: Häufige Fragen (Zugriff einschränken)](https://developer.wordpress.org/rest-api/frequently-asked-questions/)
- [REST-API-Handbuch: Authentifizierung](https://developer.wordpress.org/rest-api/using-the-rest-api/authentication/)
- [Code-Referenz: rest_authentication_errors](https://developer.wordpress.org/reference/hooks/rest_authentication_errors/)
- [WP-CLI-Handbuch: wp user application-password](https://developer.wordpress.org/cli/commands/user/application-password/)
