ووردبريس

WordPress REST API 2026: المصادقة، endpoints مخصصة، الأداء والأمان

7 دقائق للقراءة

السلسلة: Elementor 2026: Theme Builder والأداء · تأمين WordPress 2026 · أداء WordPress: Core Web Vitals

WordPress REST API هي القاعدة لكل تكامل خارجي حديث مع WordPress: تطبيقات جوّال، headless WordPress، automation عبر n8n أو Zapier، sync مع CRM، dashboards مخصصة. مُدمَجة في WordPress core منذ الإصدار 4.7 (ديسمبر 2016)، تكشف كل المحتوى — posts، pages، users، media، taxonomies، settings — كـ JSON عبر endpoints REST قياسية. مع WordPress 6.8 (أبريل 2025) و6.9 المُنتظَر نهاية 2026، الـ API تحسّنت كثيرًا: Application Passwords مُدمَجة، CORS قابلة للضبط، rate limiting أصبح ممارسة مُوثَّقة.

المتطلبات

  • WordPress 6.8+ مُثبَّت ومُحدَّث
  • وصول admin إلى wp-admin
  • أداة لإرسال طلبات HTTP (curl، Postman، Insomnia)
  • PHP 8.3 LTS على الخادم (8.4 مُفضَّلة)
  • المستوى: مطوّر متوسط، معرفة JSON وHTTP
  • الوقت المُقدَّر: 75 دقيقة

الخطوة 1 — اكتشاف endpoints المُدمَجة

كل WordPress يكشف API عند المسار /wp-json/wp/v2/. تصفّح https://moncite.com/wp-json/ يُعطي قائمة كاملة بالـ routes المتاحة.

# Lister tous les endpoints
curl -s https://moncite.com/wp-json/ | jq '.routes | keys'

# Lister les 10 derniers posts publiés
curl -s "https://moncite.com/wp-json/wp/v2/posts?per_page=10&_fields=id,title,date" | jq

# Filtrer par catégorie
curl -s "https://moncite.com/wp-json/wp/v2/posts?categories=5&per_page=20" | jq

# Récupérer un post par ID
curl -s https://moncite.com/wp-json/wp/v2/posts/123 | jq

الـ query parameters المفتاحية: per_page (1-100)، page، orderby، order، search، _fields (تصفية الحقول)، _embed (تضمين كائنات مرتبطة).

الخطوة 2 — Application Passwords للمصادقة

الـ Application Passwords مُدمَجة في WordPress 5.6+ هي الطريق الرسمي للمصادقة من تطبيقات خارجية دون كشف كلمة مرور المستخدم.

التوليد: wp-admin → Users → ملفك الشخصي → سلّ نزولًا إلى « Application Passwords »، أدخل اسم التطبيق، انقر « Add New Application Password ». تظهر كلمة المرور مرة واحدة فقط — انسخها فورًا.

curl -X POST https://moncite.com/wp-json/wp/v2/posts \
  -u "admin:xxxx xxxx xxxx xxxx xxxx xxxx" \
  -H "Content-Type: application/json" \
  -d '{
    "title": "مقال جديد من API",
    "content": "<p>المحتوى هنا</p>",
    "status": "draft",
    "categories": [3, 5]
  }'

# En PowerShell (Windows)
$cred = "admin:xxxx xxxx xxxx xxxx"
$b64 = [Convert]::ToBase64String([Text.Encoding]::UTF8.GetBytes($cred))
Invoke-RestMethod -Uri "https://moncite.com/wp-json/wp/v2/posts" \`
  -Method POST \`
  -Headers @{Authorization="Basic $b64"; "Content-Type"="application/json"} \`
  -Body '{"title":"test","status":"draft"}'

الـ Application Password مرتبطة بالمستخدم الذي ولّدها. تحترم كل صلاحياته. لإلغاء الوصول، احذف الـ Application Password — التطبيق المُتأثّر يتوقّف فورًا.

الخطوة 3 — JWT Authentication بديلة

للمنتجات حيث Application Passwords غير مناسبة، الـ JWT أنسب. الإضافة JWT Authentication for WP REST API أو Simple JWT Login تُقدّمان endpoints.

# wp-config.php : ajouter la clé secrète
define('JWT_AUTH_SECRET_KEY', 'votre-cle-secrete-32-caracteres-min');
define('JWT_AUTH_CORS_ENABLE', true);

# Login : récupérer un token
curl -X POST https://moncite.com/wp-json/jwt-auth/v1/token \
  -H "Content-Type: application/json" \
  -d '{"username":"user@email.com","password":"motdepasse"}'

# Utiliser le token
curl https://moncite.com/wp-json/wp/v2/users/me \
  -H "Authorization: Bearer eyJ0eXAi..."

JWT يبقى صالحًا حسب مدة الانتهاء (افتراضيًا 7 أيام). للأمان، خفّض إلى ساعة واحدة وأضف refresh tokens. تنبيه: لا تستخدم JWT لـ admin actions — Application Passwords أأمن.

الخطوة 4 — إنشاء endpoints مخصصة

add_action('rest_api_init', function() {
    register_rest_route('itsc/v1', '/stats/dashboard', [
        'methods'  => 'GET',
        'callback' => 'itsc_get_dashboard_stats',
        'permission_callback' => function() {
            return current_user_can('edit_posts');
        }
    ]);

    register_rest_route('itsc/v1', '/produits/(?P<id>\d+)/reserver', [
        'methods'  => 'POST',
        'callback' => 'itsc_reserver_produit',
        'permission_callback' => function() {
            return is_user_logged_in();
        },
        'args' => [
            'id' => [
                'validate_callback' => function($p) { return is_numeric($p); }
            ],
            'quantite' => [
                'required' => true,
                'type' => 'integer',
                'minimum' => 1
            ]
        ]
    ]);
});

function itsc_get_dashboard_stats(WP_REST_Request $request) {
    return [
        'posts_count'    => wp_count_posts()->publish,
        'comments_count' => wp_count_comments()->approved,
        'users_count'    => count_users()['total_users']
    ];
}

function itsc_reserver_produit(WP_REST_Request $request) {
    $produit_id = (int) $request['id'];
    $quantite   = (int) $request['quantite'];

    $stock = (int) get_post_meta($produit_id, 'stock', true);
    if ($stock < $quantite) {
        return new WP_Error('stock_insuffisant', 'Stock insuffisant', ['status' => 422]);
    }

    update_post_meta($produit_id, 'stock', $stock - $quantite);
    return ['succes' => true, 'stock_restant' => $stock - $quantite];
}

ثلاث ممارسات مهمة. permission_callback إلزامية. args مع validate_callback يمنع البيانات غير الصالحة. إرجاع WP_Error مع status يُولّد كود HTTP الصحيح.

الخطوة 5 — تجاوز .htaccess hardened

كثير من المواقع المُؤمَّنة تحجب /wp-json/* في .htaccess. استخدم المسار البديل:

# Au lieu de :
curl https://moncite.com/wp-json/wp/v2/posts/123

# Utilise :
curl "https://moncite.com/index.php?rest_route=/wp/v2/posts/123"

# Avec paramètres (séparateur & au lieu de ?)
curl "https://moncite.com/index.php?rest_route=/wp/v2/posts&per_page=5"

# POST identique
curl -X POST "https://moncite.com/index.php?rest_route=/wp/v2/posts" \
  -u "admin:app-password" \
  -H "Content-Type: application/json" \
  -d '{"title":"test","status":"draft"}'

هذا المسار يمرّ عبر index.php الذي لا يُحجب من .htaccess الـ hardened. الأداء مطابق.

الخطوة 6 — تحسين الأداء

// 1. Caching agressif des endpoints publics
add_filter('rest_post_dispatch', function($response, $server, $request) {
    if ($request->get_method() === 'GET' && !is_user_logged_in()) {
        $response->header('Cache-Control', 'public, max-age=300');
        $response->header('Vary', 'Accept-Encoding');
    }
    return $response;
}, 10, 3);

// 2. Réduire payload via _fields
// /wp-json/wp/v2/posts?_fields=id,title,date,excerpt

// 3. Object cache (Redis ou Memcached)
define('WP_CACHE', true);

على موقع بـ 500 posts، استدعاء /wp/v2/posts?per_page=100 يستغرق عادةً 800ms-2s دون cache. مع object cache Redis + headers HTTP cache، ينخفض إلى 50-100ms. لـ APIs عامة عالية الحركة، أضف CDN (Cloudflare) أمام endpoints.

الخطوة 7 — Rate limiting وأمان

// 1. Rate limiting basique via filter
add_filter('rest_pre_dispatch', function($result, $server, $request) {
    if (is_wp_error($result)) return $result;
    
    $ip = $_SERVER['REMOTE_ADDR'] ?? '';
    $key = 'rest_rl_' . md5($ip);
    $count = (int) get_transient($key);
    
    if ($count >= 60) {
        return new WP_Error('rate_limit', 'Trop de requêtes', ['status' => 429]);
    }
    
    set_transient($key, $count + 1, 60);
    return $result;
}, 10, 3);

// 2. Désactiver users endpoint pour non-authentifiés
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;
});

// 3. CORS strict
add_action('rest_api_init', function() {
    remove_filter('rest_pre_serve_request', 'rest_send_cors_headers');
    add_filter('rest_pre_serve_request', function($value) {
        $origin = $_SERVER['HTTP_ORIGIN'] ?? '';
        $allowed = ['https://app.moncite.com'];
        if (in_array($origin, $allowed, true)) {
            header("Access-Control-Allow-Origin: $origin");
            header('Access-Control-Allow-Credentials: true');
        }
        return $value;
    });
}, 15);

للمواقع الإنتاجية، رصد محاولات إساءة عبر Wordfence أو fail2ban على access logs.

الخطوة 8 — استهلاك في JavaScript حديث

// Fetch natif avec gestion d'erreur
async function fetchPosts() {
    try {
        const response = await fetch(
            'https://moncite.com/wp-json/wp/v2/posts?per_page=10&_fields=id,title,excerpt,date',
            { headers: { 'Accept': 'application/json' } }
        );
        if (!response.ok) {
            throw new Error('HTTP ' + response.status);
        }
        return await response.json();
    } catch (err) {
        console.error('Erreur API :', err);
        return [];
    }
}

// Création authentifiée (Application Password)
async function creerPost(token, data) {
    const auth = 'Basic ' + btoa('admin:' + token);
    const response = await fetch('https://moncite.com/wp-json/wp/v2/posts', {
        method: 'POST',
        headers: {
            'Authorization': auth,
            'Content-Type': 'application/json'
        },
        body: JSON.stringify(data)
    });
    return await response.json();
}

// Avec @wordpress/api-fetch (plugin/theme JS)
import apiFetch from '@wordpress/api-fetch';
const posts = await apiFetch({ path: '/wp/v2/posts?per_page=10' });

أخطاء شائعة

الخطأ السبب الحل
401 Unauthorized عند POST Application Password خاطئة تحقّق من Application Password وصلاحيات المستخدم
403 Forbidden على endpoint عام .htaccess hardened أو security plugin استخدم /index.php?rest_route=
404 على endpoint مخصص permalinks غير مُحدَّثة Settings → Permalinks → Save
CORS error في المتصفّح Origin غير مُصرَّح أضف Access-Control-Allow-Origin
Endpoint مخصص يُرجع HTML error PHP في callback تحقّق من debug.log، فعّل WP_DEBUG=true
Body فارغ في POST Content-Type غير مُعَدّ أضف -H "Content-Type: application/json"

الأسئلة الشائعة

REST API أم GraphQL؟
REST مُدمَج في core، صفر إعداد. GraphQL عبر إضافة WPGraphQL، أنسب للتطبيقات بـ schema معقد.

هل أُعطّل REST API؟
لا تمامًا — Gutenberg وكثير من core features تعتمد عليه. عطّل فقط للمستخدمين غير المصادَقين عبر filter rest_authentication_errors.

كيف نُؤمّن endpoint مخصص؟
permission_callback إلزامية. لا تستخدم __return_true أبدًا للـ endpoints التي تكتب.

هل REST API يدعم webhooks؟
ليس أصلًا. إضافات مثل WP Webhooks تُقدّم webhooks خارجية.

أداء على موقع كبير؟
محدود بـ PHP/MySQL. لـ headless بـ 10k+ requests/يوم، object cache Redis + CDN إلزاميان.

مقالات ذات صلة

Sponsoriser ce contenu

Cet emplacement est à vous

Position premium en fin d'article — c'est l'instant où les lecteurs sont le plus engagés. Réservez cet espace pour votre marque, votre formation ou votre offre.

Recevoir nos tarifs
Publicité