 Autor: [Monika Wojciechowska](/autorzy/monika-wojciechowska) Specjalistka SEO i treści webowych · Zweryfikowano Kwiecień 2026

1.  [Strona główna](/) ›
2.  [Baza wiedzy](/baza-wiedzy/) ›
3.  WordPress REST API — bezpieczeństwo

# WordPress REST API — zabezpieczenie i optymalizacja

Opublikowano: 9 kwietnia 2026 · Kategoria: WordPress / Bezpieczeństwo

WordPress REST API (dostępne pod `/wp-json/`) to potężne narzędzie dla headless WordPress, aplikacji mobilnych i integracji z zewnętrznymi serwisami. Niestety to też jeden z najpopularniejszych wektorów ataków — ujawnia listę użytkowników, umożliwia brute-force i jest używane przez boty do skanowania podatności. Oto jak go zabezpieczyć bez psucia funkcjonalności.

## Czym jest WP REST API i dlaczego to attack surface?

REST API WordPress zostało wprowadzone w wersji 4.4 i jest aktywne domyślnie na każdej instalacji. Dostępne endpointy możesz sprawdzić:

\# Sprawdź dostępne endpointy
curl https://twoja-domena.pl/wp-json/

# Endpointy użytkowników (potencjalnie wrażliwe)
curl https://twoja-domena.pl/wp-json/wp/v2/users

# Posty i strony publiczne
curl https://twoja-domena.pl/wp-json/wp/v2/posts
curl https://twoja-domena.pl/wp-json/wp/v2/pages

Endpoint `/wp/v2/users` domyślnie zwraca loginy wszystkich użytkowników z opublikowanymi postami — to gotowa lista do ataków brute-force na wp-login.php.

## Blokada user enumeration przez REST API

Dodaj do `functions.php` aktywnego motywu (lub lepiej — do własnej wtyczki mu-plugins):

<?php
/\*\*
 \* Blokada user enumeration przez REST API i przez ?author=N
 \* Dodaj do: /wp-content/mu-plugins/security-hardening.php
 \*/

// 1. Ukryj endpoint /wp/v2/users dla niezalogowanych
add\_filter( 'rest\_endpoints', function( $endpoints ) {
    if ( ! is\_user\_logged\_in() ) {
        unset( $endpoints\['/wp/v2/users'\] );
        unset( $endpoints\['/wp/v2/users/(?P<id>\[\\d\]+)'\] );
    }
    return $endpoints;
} );

// 2. Blokada ?author=N redirect (ujawnia login przez URL)
add\_action( 'template\_redirect', function() {
    if ( isset( $\_GET\['author'\] ) && ! is\_user\_logged\_in() ) {
        wp\_die( 'Forbidden', 'Forbidden', \[ 'response' => 403 \] );
    }
} );

// 3. Usuń login z REST API responses
add\_filter( 'rest\_prepare\_user', function( $response ) {
    if ( ! is\_user\_logged\_in() ) {
        $data = $response->get\_data();
        unset( $data\['slug'\] );   // login ukryty w slug
        $response->set\_data( $data );
    }
    return $response;
} );

## Wyłączenie REST API dla niezalogowanych (selektywne)

Całkowite wyłączenie REST API może zepsuć wtyczki. Bezpieczniejsze podejście — blokada tylko wrażliwych namespace:

<?php
// Blokada dostępu do REST API dla niezalogowanych
// (zostawia publiczne endpointy dla WooCommerce, CF7 itp.)
add\_filter( 'rest\_authentication\_errors', function( $result ) {
    if ( ! empty( $result ) ) {
        return $result;
    }
    if ( ! is\_user\_logged\_in() ) {
        $route = $GLOBALS\['wp'\]->query\_vars\['rest\_route'\] ?? '';
        // Blokuj TYLKO wrażliwe namespace
        $blocked = \[ '/wp/v2/users', '/wp/v2/settings' \];
        foreach ( $blocked as $path ) {
            if ( str\_starts\_with( $route, $path ) ) {
                return new WP\_Error(
                    'rest\_forbidden',
                    'Dostęp zabroniony.',
                    \[ 'status' => 403 \]
                );
            }
        }
    }
    return $result;
} );

## Rate limiting w Nginx dla /wp-json/

Dodaj rate limiting dla endpointu REST API w konfiguracji Nginx:

\# /etc/nginx/nginx.conf (w bloku http {})
limit\_req\_zone $binary\_remote\_addr zone=wp\_rest:10m rate=10r/s;
limit\_req\_zone $binary\_remote\_addr zone=wp\_login:10m rate=1r/s;

\# /etc/nginx/sites-available/twoja-domena.conf
server {
    # ...

    # Rate limiting dla REST API (10 req/s, burst 20)
    location /wp-json/ {
        limit\_req zone=wp\_rest burst=20 nodelay;
        limit\_req\_status 429;
        try\_files $uri $uri/ /index.php$is\_args$args;
    }

    # Rate limiting dla wp-login.php (1 req/s, bez burst)
    location = /wp-login.php {
        limit\_req zone=wp\_login;
        limit\_req\_status 429;
        fastcgi\_pass unix:/run/php/php8.2-fpm.sock;
        include fastcgi\_params;
        fastcgi\_param SCRIPT\_FILENAME $document\_root$fastcgi\_script\_name;
    }
}

## JWT Authentication dla REST API

JWT (JSON Web Token) umożliwia bezstanowe uwierzytelnianie dla aplikacji zewnętrznych. Zainstaluj wtyczkę **JWT Auth for WP REST API**:

\# wp-config.php — dodaj klucz JWT
define( 'JWT\_AUTH\_SECRET\_KEY', 'twoj-dlugi-tajny-klucz-min-32-znaki' );
define( 'JWT\_AUTH\_CORS\_ENABLE', true );

\# Krok 1: Pobierz token JWT
curl -X POST https://twoja-domena.pl/wp-json/jwt-auth/v1/token \\
  -H "Content-Type: application/json" \\
  -d '{"username":"admin","password":"haslo"}'

# Odpowiedź:
# { "token": "eyJ0eXAiOiJKV1QiLC...", "user\_email": "...", "user\_display\_name": "..." }

# Krok 2: Użyj tokena do autoryzowanych zapytań
curl -X GET https://twoja-domena.pl/wp-json/wp/v2/users \\
  -H "Authorization: Bearer eyJ0eXAiOiJKV1QiLC..."

## Application Passwords (WordPress 5.6+)

Wbudowana alternatywa dla JWT — bez dodatkowej wtyczki. Generujesz hasło per aplikacja w profilu użytkownika (Użytkownicy → Twój profil → Hasła aplikacji):

\# Użycie Application Password (Basic Auth)
# Format: "username:application\_password" zakodowany w base64
curl -X GET https://twoja-domena.pl/wp-json/wp/v2/users/me \\
  -H "Authorization: Basic $(echo -n 'admin:xxxx xxxx xxxx xxxx' | base64)"

# Lub wprost (mniej bezpieczne — hasło w historii bash)
curl -u "admin:xxxx xxxx xxxx xxxx" \\
  https://twoja-domena.pl/wp-json/wp/v2/posts

Uwaga: Application Passwords wymagają HTTPS — WordPress automatycznie odrzuca żądania przez HTTP.

## Fail2ban — blokada brute-force przez REST API

\# /etc/fail2ban/filter.d/wordpress-rest.conf
\[Definition\]
failregex = ^<HOST> .\* "POST /wp-json/jwt-auth/v1/token.\*" (401|403|429)
            ^<HOST> .\* "GET /wp-json/wp/v2/users.\*" (403|429)
ignoreregex =

\# /etc/fail2ban/jail.local
\[wordpress-rest\]
enabled  = true
filter   = wordpress-rest
logpath  = /var/log/nginx/access.log
maxretry = 5
findtime = 300
bantime  = 3600

\# Restart i weryfikacja fail2ban
systemctl restart fail2ban
fail2ban-client status wordpress-rest

## Nagłówki CORS

Jeśli REST API jest używane przez aplikację frontendową z innej domeny, skonfiguruj CORS w Nginx (zamiast polegać na domyślnych ustawieniach WordPress):

location /wp-json/ {
    # Ogranicz CORS do zaufanych domen
    add\_header Access-Control-Allow-Origin "https://twoja-app.pl" always;
    add\_header Access-Control-Allow-Methods "GET, POST, PUT, DELETE, OPTIONS" always;
    add\_header Access-Control-Allow-Headers "Authorization, Content-Type" always;

    if ($request\_method = OPTIONS) {
        return 204;
    }

    try\_files $uri $uri/ /index.php$is\_args$args;
}

## Najczęstsze pytania

Czy wyłączenie REST API dla niezalogowanych zepsuje moją stronę? +

Zależy od wtyczek. Niektóre wtyczki (np. Contact Form 7, WooCommerce, Elementor) używają REST API nawet dla niezalogowanych użytkowników. Dlatego zamiast blokować wszystkie endpointy, zablokuj tylko wrażliwe namespace (wp/v2/users) i ogranicz dostęp przez rate limiting. Przetestuj stronę po każdej zmianie — włącz debug mode i sprawdź konsolę błędów przeglądarki.

Czym różni się JWT od Application Passwords w WordPress? +

Application Passwords (WordPress 5.6+) to wbudowana funkcja — generujesz hasło per aplikacja w profilu użytkownika. Wymaga Basic Auth (username:app\_password w nagłówku). JWT Authentication to standard tokenów: klient loguje się raz i dostaje token ważny przez określony czas (np. 24h), który dołącza do każdego żądania. JWT wymaga wtyczki (np. JWT Auth for WP REST API). Application Passwords są prostsze do użycia, JWT lepszy dla mobile apps i SPAs.

Jak sprawdzić czy moja strona jest podatna na user enumeration przez REST API? +

Wejdź w przeglądarce na: twoja-domena.pl/wp-json/wp/v2/users — jeśli zwróci listę użytkowników z login, name, id to jesteś podatny. Attacker może użyć tej listy do brute-force logowania. Poprawka: add\_filter("rest\_endpoints") + usunięcie endpointu users lub zwracanie pustej tablicy dla niezalogowanych. Sprawdź też ?author=1 redirect który ujawnia login przez URL.

Czy rate limiting Nginx chroni przed atakami DDoS na REST API? +

Częściowo. Nginx limit\_req\_zone skutecznie blokuje proste brute-force i scraping (do ~1000 req/s per IP). Przy prawdziwym DDoS z tysięcy IP potrzebna jest ochrona na poziomie sieci (Cloudflare, dostawca VPS). Dobrym uzupełnieniem jest fail2ban który blokuje IP po X błędach 429/403 w logach Nginx — automatycznie dodaje regułę iptables.

## Sprawdź oferty pasujące do tego scenariusza

Poniżej masz szybkie przejścia do ofert i stron z kodami rabatowymi tam, gdzie są dostępne.

LH.pl

Hosting WordPress z firewallem WAF i ochroną przed atakami na wp-json

Bezpieczeństwo

[Aktywuj rabat →](/out/lh-pl)

#Reklama · link partnerski

[Zobacz kod rabatowy →](/kody-rabatowe/lh-pl)

Zenbox

Hosting z ModSecurity WAF — automatyczna ochrona REST API przed exploitami

ModSecurity

[Aktywuj rabat →](/out/zenbox)

#Reklama · link partnerski

[Zobacz kod rabatowy →](/kody-rabatowe/zenbox)

Contabo

VPS z pełną kontrolą — skonfiguruj Nginx rate limiting i fail2ban samodzielnie

Full control

[Aktywuj rabat →](/out/contabo)

#Reklama · link partnerski

[Zobacz kod rabatowy →](/kody-rabatowe/contabo)

## Powiązane strony

-   [Bezpieczeństwo WordPress — kompletny przewodnik](/baza-wiedzy/bezpieczenstwo-wordpress-hosting)
-   [Nginx rate limiting i load balancer](/baza-wiedzy/nginx-load-balancer-konfiguracja)
-   [PHP-FPM — konfiguracja i optymalizacja](/baza-wiedzy/php-fpm-konfiguracja-optymalizacja)
-   [Wszystkie artykuły](/baza-wiedzy/)