Ответ @ssnepenthe прав, говоря, что используемый вами хук не является правильным во входящем запросе.
Информация запроса немедленно доступна для PHP, поэтому вы можете использовать самый ранний доступный хук для их проверки. И если вы хотите сделать это в контексте API запроса, вы должны использовать самый ранний хук запроса REST API. 'rest_pre_dispatch'
предложено @ssnepenthe хорошо, может быть, другой вариант может бытьrest_authentication_errors
, который позволит вам вернуть ошибку в случае, если что-то не так.
Но Джек Йоханссон прав, говоря что HTTP-заголовки (например, заголовок referer, используемый в aswer @ ssnepenthe) не являются надежными, так как они очень легко изменяются клиентом. Так что это все равно, что поставить охранника перед дверью, который просто спросит: "Безопасно ли вам входить?" всем, кто хочет войти: это не сработает.
Но решение, предложенное ответом Джека Йоханссона (одноразовый номер), также не является реальным решением: весь смысл одноразовых номеров состоит в том, чтобы изменяться со временем, и у конечной точки общедоступного API не может быть вещей, которые изменяются в зависимости от времени. Более того, одноразовые номера WP заслуживают доверия только тогда, когда есть вошедший в систему пользователь, что может не соответствовать общедоступному API и если пользователь вошел в систему, вероятно, нет причин проверять входящий домен: вы доверяете пользователю, а не пользователю. пользовательская машина.
Так что делать?
Ну, даже если заголовки HTTP не являются надежными, не вся доступная информация $_SERVER
поступает из заголовков.
Обычно все $_SERVER
значения, чьи ключи начинаются с имени, начинаются с HTTP_
заголовков и должны рассматриваться как небезопасный ввод пользователя .
Но, к примеру, $_SERVER['REMOTE_ADDR']
содержит IP - адрес , используемый для подключения TCP к вашему серверу, что означает , что он является доверительным 1 .
Что также означает, что либо:
- правильная настройка сервера для генерации
$_SERVER['REMOTE_HOST']
значения (например, в Apache, которое вам нужно HostnameLookups On
внутри вашего httpd.conf
) это значение
- использование
gethostbyaddr
для обратного поиска DNS для разрешения доменного имени IP-адреса, хранящегося в$_SERVER['REMOTE_ADDR']
вы можете получить достаточно надежно имя хоста , которое вы могли бы использовать , чтобы проверить против белого списка (для кода, вы можете адаптировать код из @ ssnepenthe - х aswer , где вы бы заменить $referer = $request->get_header('referer')
с $referer = gethostbyaddr($_SERVER['REMOTE_ADDR'])
).
Но есть проблема .
Если ваш веб-сервер находится за обратным прокси-сервером (на самом деле, это довольно распространенное решение), TCP-подключение к веб-серверу фактически осуществляется через прокси-сервер, так $_SERVER['REMOTE_ADDR']
же как и IP-адрес прокси-сервера, а не IP-адрес клиента, который первоначально отправил запрос.
Исходный IP-адрес запроса в таких случаях обычно доступен как $_SERVER['HTTP_X_FORWARDED_FOR']
, но будучи одним из тех $_SERVER
значений, которые начинаются с HTTP_
него, на самом деле нельзя доверять.
Таким образом, если ваш веб-сервер находится за обратным прокси-сервером 2, даже $_SERVER['REMOTE_ADDR']
он не будет полезен для такой защиты, а белый список на основе домена может быть реализован только на уровне прокси.
Короче говоря, надежное решение для защиты конечных точек API должно быть либо реализовано с использованием какого-либо реального механизма аутентификации (например, oAuth), либо оно должно действовать непосредственно на конфигурации сервера, а не на уровне приложения.
Ноты
1 Теоретически, он может быть взломан, если кто-то взломал вашего интернет-провайдера или если злоумышленник действует изнутри вашей локальной сети, в обоих случаях вы можете сделать очень мало для обеспечения безопасности.
2 Если вы не знаете, используете ли вы обратный прокси-сервер, вы можете отправить запрос со своего локального ПК и проверить, соответствует ли $_SERVER['REMOTE_ADDR']
на сервере IP-адрес локального ПК, а также, если $_SERVER['HTTP_X_FORWARDED_FOR']
он присутствует, и соответствует ли он IP-адресу локального ПК.