由于项目实际需求。不能完全禁用REST API。但大部分项目中会禁用REST API。那么就有了下面的代码。下面的代码可以在主题的functions.php中require进来。

注:为了方便使用,可以在主代码引入之前定义一个全局变量REST_API_USABILITY。如果设置为false将完全禁用REST API。如果设置为true则局部开放,但是默认的端点(end points)依然是被关闭的状态。如果需要开放指定端点,请在主代码的$points数组中去掉想要开放的端点名称,并设置REST_API_USABILITY为true。

define('REST_API_USABILITY', false);
//(bool) false for Disable,true for Partial support.
主要代码如下:

其中可设置白名单OPE23_REST_API_DEFAULT_IP_WHITELIST。对白名单里的IP,REST API完全开放。白名单默认有127.0.0.1。即本地测试REST API可用。

<?php
defined('WPINC') || die();
define('OPE23_REST_API_DEFAULT_IP_WHITELIST', array('127.0.0.1', '::1'));
function ope23_completely_disable_rest_api()
{
    if (!defined('OPE23_IS_REST_API_DISABLED')) {
        define('OPE23_IS_REST_API_DISABLED', true);
    }
}
function ope23_disable_rest_api_user_enumeration()
{
    if (!defined('OPE23_IS_REST_API_USER_ENUMERATION_DISABLED')) {
        define('OPE23_IS_REST_API_USER_ENUMERATION_DISABLED', true);
    }
}
function ope23_rest_api_init()
{
    $is_rest_api_available = true;
    $is_attempting_user_enumeration = false;
    $is_user_an_administrator = false;
    if ($is_user_authenticated = is_user_logged_in()) {
        $is_user_an_administrator = current_user_can('administrator');
    }
    $is_user_authorised = ($is_user_authenticated && $is_user_an_administrator);
    $is_remote_ip_whitelisted = false;
    if (defined('OPE23_REST_API_IP_WHITELIST') && is_array(OPE23_REST_API_IP_WHITELIST)) {
        $is_remote_ip_whitelisted = in_array($_SERVER['REMOTE_ADDR'], OPE23_REST_API_IP_WHITELIST);
    } elseif (defined('OPE23_REST_API_DEFAULT_IP_WHITELIST') && is_array(OPE23_REST_API_DEFAULT_IP_WHITELIST)) {
        $is_remote_ip_whitelisted = in_array($_SERVER['REMOTE_ADDR'], OPE23_REST_API_DEFAULT_IP_WHITELIST);
    } else {
        // ...
    }
    $is_ip_block_requested = false;
    $is_rest_api_disabled = false;
    if (defined('OPE23_IS_REST_API_DISABLED')) {
        $is_rest_api_disabled = (OPE23_IS_REST_API_DISABLED === true);
    }
    $is_public_user_enumeration_disabled = true;
    if (defined('OPE23_IS_REST_API_USER_ENUMERATION_DISABLED') && (OPE23_IS_REST_API_USER_ENUMERATION_DISABLED !== true)) {
        $is_public_user_enumeration_disabled = false;
    }
    $is_endpoint_blocked = false;
    if (!$is_user_authenticated && !$is_remote_ip_whitelisted && $is_public_user_enumeration_disabled) {
        $prefix = rest_get_url_prefix();
        $points = array('media', 'users', 'pages', 'taxonomies', 'types', 'settings', 'themes', 'plugins', 'posts', 'categories', 'tags', 'comments', 'statuses', 'search');
        foreach ($points as $point) {
            $endpoint_path = '/' . $prefix . '/wp/v2/' . $point;
            if ((isset($_SERVER['REQUEST_URI']) && (strpos($_SERVER['REQUEST_URI'], $endpoint_path) !== false))
                ||
                (isset($_REQUEST['rest_route']) && (strpos($_SERVER['rest_route'], $endpoint_path) !== false))
            ) {
                $is_endpoint_blocked = true;
                $is_ip_block_requested = true;
            }
        }
    }
    $http_error_code = null;
    $is_rest_api_available = false;
    if ($is_user_authorised) {
        // ...
    } elseif ($is_remote_ip_whitelisted) {
        // ...
    } elseif ($is_rest_api_disabled) {
        //...
        $http_error_code = 404;
    } elseif (!$is_endpoint_blocked) {
        // ...
    } else {
        $http_error_code = 404;
    }

    if ($http_error_code == 404) {
        header("Status: 404 Not Found");
        $GLOBALS['wp_query']->set_404();
        status_header(404);
        nocache_headers();
        include get_query_template('404');
        exit;
    } elseif (!empty($http_error_code)) {
        http_response_code($http_error_code);
        die('ERR: ' . $http_error_code);
    } else {
        // OK.
    }
}
add_action('rest_api_init', 'ope23_rest_api_init', 100);

if (!REST_API_USABILITY) {
    ope23_completely_disable_rest_api();
} else {
    ope23_disable_rest_api_user_enumeration();
}
相关文章