WordPress REST API にレート制限を特定ユーザー以外に設定する

ブログ

以下の記事ではWordPressのカスタムテーブルデータを取得するAPIを作成して、APIレート制限をかける方法を紹介しました。

今回は、その制限を管理者ユーザーからは除外する修正を紹介します。

修正後のコード

/**
 * APIキーの照合とレート制限を行うコールバック関数
 */
function movie_api_key_check(WP_REST_Request $request) {
    $api_key = $request->get_header('X-API-Key');

    if (empty($api_key)) {
        return new WP_Error('rest_forbidden', 'APIキーが必要です。', array('status' => 401));
    }

    // APIキーを持つユーザーを検索
    $args = array(
        'meta_key'    => 'api_key',
        'meta_value'  => $api_key,
        'number'      => 1,
        'count_total' => false,
    );
    $users = get_users($args);

    if (empty($users)) {
        return new WP_Error('rest_forbidden', '正しいAPIキーが必要です。', array('status' => 401));
    }

    // ユーザー情報を取得
    $user = $users[0];

    // 管理者ならレート制限なし
    if (user_can($user, 'manage_options')) {
        return true;
    }

    // レート制限をチェック
    $limit_result = check_api_rate_limit($api_key);
    if (is_wp_error($limit_result)) {
        return $limit_result;
    }

    return true;
}

/**
 * APIのレート制限をチェック
 */
function check_api_rate_limit($api_key) {
    $minute_limit = 10;  // 1分間に10回
    $daily_limit = 100;   // 24時間に100回

    $minute_key = "api_rate_{$api_key}_minute";
    $daily_key = "api_rate_{$api_key}_daily";

    $minute_count = get_transient($minute_key) ?: 0;
    $daily_count = get_transient($daily_key) ?: 0;

    if ($minute_count >= $minute_limit) {
        return new WP_Error('rest_forbidden', '1分間のAPIリクエスト制限を超えました。', array('status' => 429));
    }

    if ($daily_count >= $daily_limit) {
        return new WP_Error('rest_forbidden', '24時間のAPIリクエスト制限を超えました。', array('status' => 429));
    }

    // カウントを更新
    set_transient($minute_key, $minute_count + 1, 60);       // 60秒有効
    set_transient($daily_key, $daily_count + 1, 24 * 60 * 60); // 24時間有効

    return true;
}

// GETリクエスト用のエンドポイントを登録
function register_movie_data_get_endpoint() {
    register_rest_route('movie/v1', '/get/', array(
        'methods'             => 'GET',
        'callback'            => 'get_movie_data',
        'permission_callback' => 'movie_api_key_check',
    ));
}
add_action('rest_api_init', 'register_movie_data_get_endpoint');

修正点は以下の通りです。管理者ユーザーに対してレート制限を解除するために、特定の条件でレート制限を適用しないように変更しました。

ユーザーの権限をチェック

// ユーザー情報を取得
$user = $users[0];

// 管理者ならレート制限なし
if (user_can($user, 'manage_options')) {
    return true;
}
  • まず、$users[0] から取得したユーザーオブジェクトを $user に保存します。
  • user_can($user, 'manage_options') を使って、ユーザーが「管理者権限(manage_options)」を持っているかどうかをチェックします。
  • manage_options 権限は、通常「管理者」ユーザーにのみ付与される権限であり、この権限を持つユーザーは WordPress の設定などを変更できるユーザーです。
  • もしユーザーが管理者であれば、return true; でレート制限をスキップし、APIリクエストを許可します。

管理者以外のユーザーにレート制限を適用

// レート制限をチェック
$limit_result = check_api_rate_limit($api_key);
if (is_wp_error($limit_result)) {
    return $limit_result;
}
  • 管理者でないユーザーに対しては、check_api_rate_limit() 関数を呼び出して、レート制限を確認します。
  • check_api_rate_limit() は、1分間および24時間のリクエスト回数が制限を超えていないかどうかをチェックし、制限を超えていた場合にはエラーメッセージ(WP_Error)を返します。

まとめ

  • 管理者(administrator)にはレート制限を適用しないように、user_can() 関数で権限をチェックして、管理者の場合はそのままtrueを返してアクセスを許可しています。
  • 管理者以外のユーザーには、レート制限を適用して、制限を超えた場合はエラーを返します。

この修正により、管理者は制限なくAPIを利用でき、その他のユーザーにはレート制限が適用されます。

タイトルとURLをコピーしました