I was looking into improving the security of my Wordpress site and while doing so discovered that the WP REST API is enabled by default (as of WP 4.4 if I remember correctly).
What is the safe way to disable it?
"Safe" here means that it won't cause unintended side effects, such as not breaking any other WP core functionality.
One possible approach is to use .htaccess
to rewrite the rules, but surprisingly I didn't find any "official" instructions for doing this.
Any help or advice would be greatly appreciated :)
renew: Third party plugins are not the solution I'm looking for. Although I know there are many tools that can solve this task, they contain many extra features that can slow down the website. I'm hoping there's a one-line solution to this problem without the additional overhead of a plugin.
Update 2: This is the official opinion of WordPress: https://developer.wordpress.org/rest-api/using-the-rest-api/frequently-asked-questions/#can-i-disable-the-rest-api p>
According to this, the WordPress team hopes that future WP features will rely on the new REST API. This means there is no safety way to disable the REST API.
We just hope there are enough security experts responsible for WP security.
Update 3:
There is a workaround available in the WordPress API Manual - you can require authentication for all requests
This ensures that anonymous access to the website's REST API is disabled and only authenticated requests are valid.
P粉4784456712024-01-11 15:20:53
The accepted answer disables all API calls for unauthenticated users, but many plugins these days rely on this API functionality.
Disabling all calls will result in unexpected site behavior, which has also happened to me when using this code.
For example, ContactForm7 uses this API to send contact information to the database (I think) and do ReCaptcha validation.
I think it's best to disable certain (default) endpoints for unauthenticated users, like this:
// Disable some endpoints for unauthenticated users add_filter( 'rest_endpoints', 'disable_default_endpoints' ); function disable_default_endpoints( $endpoints ) { $endpoints_to_remove = array( '/oembed/1.0', '/wp/v2', '/wp/v2/media', '/wp/v2/types', '/wp/v2/statuses', '/wp/v2/taxonomies', '/wp/v2/tags', '/wp/v2/users', '/wp/v2/comments', '/wp/v2/settings', '/wp/v2/themes', '/wp/v2/blocks', '/wp/v2/oembed', '/wp/v2/posts', '/wp/v2/pages', '/wp/v2/block-renderer', '/wp/v2/search', '/wp/v2/categories' ); if ( ! is_user_logged_in() ) { foreach ( $endpoints_to_remove as $rem_endpoint ) { // $base_endpoint = "/wp/v2/{$rem_endpoint}"; foreach ( $endpoints as $maybe_endpoint => $object ) { if ( stripos( $maybe_endpoint, $rem_endpoint ) !== false ) { unset( $endpoints[ $maybe_endpoint ] ); } } } } return $endpoints; }
This way, the only endpoints opened now are the ones installed by the plugin.
For a complete list of endpoints active on your site, see https://YOURSITE.com/wp-json/
You are free to edit the $endpoints_to_remove
array as per your requirements.
If you have custom post types, make sure to add them all to the list.
In my case, I also changed the default endpoint prefix from wp-json
to mybrand-api
. This should act as a deterrent to bots making thousands of brute force requests.
This is what I did:
// Custom rest api prefix (Make sure to go to Dashboard > Settings > Permalinks and press Save button to flush/rewrite url cache ) add_filter( 'rest_url_prefix', 'rest_api_url_prefix' ); function rest_api_url_prefix() { return 'mybrand-api'; }
P粉5123632332024-01-11 12:47:36
Based on the author's original question, I chose option 2 from the official WordPress recommendation (https://developer.wordpress.org/rest-api/using-the-rest-api/frequently-asked-questions /#can-i-disable-the-rest-api). So just put in your functions.php and only let logged in users use the rest of the API (but just cross check the original link in case my code block is outdated ;) ): Updated (October 1, 2021):
add_filter( 'rest_authentication_errors', function( $result ) { // If a previous authentication check was applied, // pass that result along without modification. if ( true === $result || is_wp_error( $result ) ) { return $result; } // No authentication has been performed yet. // Return an error if user is not logged in. if ( ! is_user_logged_in() ) { return new WP_Error( 'rest_not_logged_in', __( 'You are not currently logged in.' ), array( 'status' => 401 ) ); } // Our custom authentication check should have no effect // on logged-in requests return $result; });