La réponse de @ssnepenthe a raison de dire que le crochet que vous utilisez n'est pas le bon dans la demande entrante.
Les informations de demande sont immédiatement disponibles pour PHP, vous pouvez donc utiliser le premier crochet disponible pour les vérifier. Et si vous souhaitez le faire dans le contexte de l'API de demande, vous devez utiliser le premier crochet d'une demande d'API REST. 'rest_pre_dispatch'
suggéré par @ssnepenthe est très bien, peut-être une autre option pourrait rest_authentication_errors
vous permettre de retourner une erreur en cas de problème.
Mais Jack Johansson a raison de dire que les en-têtes HTTP (comme l'en-tête de référence utilisé dans l'aswer de @ ssnepenthe) ne sont pas fiables, car ils sont très facilement modifiés par le client. Donc, ce serait comme mettre un gardien de sécurité devant une porte qui demande simplement "c'est sûr de vous laisser entrer?" à tous ceux qui veulent y entrer: ça ne marchera pas.
Mais la solution proposée par Jack Johansson (un nonce) n'est pas non plus une vraie solution: tout le point des nonces est de changer avec le temps, et un point de terminaison API public ne peut pas avoir des choses qui changent en fonction du temps. De plus, les nonces WP ne sont fiables que lorsqu'il y a un utilisateur connecté, ce qui peut ne pas être le cas pour une API publique et si un utilisateur est connecté, il n'y a probablement aucune raison de vérifier le domaine entrant: vous faites confiance à l'utilisateur, pas au machine utilisateur.
Alors que faire?
Eh bien, même si les en-têtes HTTP ne sont pas fiables, toutes les informations disponibles ne $_SERVER
proviennent pas des en-têtes.
Normalement, toutes les $_SERVER
valeurs dont les clés commencent par qui commencent HTTP_
proviennent d'en-têtes et doivent être traitées comme des entrées utilisateur non sécurisées .
Mais, par exemple, $_SERVER['REMOTE_ADDR']
contient l'adresse IP utilisée pour la connexion TCP à votre serveur, ce qui signifie qu'elle est fiable 1 .
Ce qui signifie également que:
- configurer correctement le serveur pour générer la
$_SERVER['REMOTE_HOST']
valeur (par exemple dans Apache dont vous aurez besoin HostnameLookups On
dans votre httpd.conf
) cette valeur
- utilisation
gethostbyaddr
pour effectuer une recherche DNS inversée pour résoudre le nom de domaine de l'adresse IP stockée dans$_SERVER['REMOTE_ADDR']
vous pourriez obtenir assez fiable un nom d'hôte que vous pouvez utiliser pour vérifier contre un whitelist (pour le code, vous pouvez adapter le code de @ la aswer de ssnepenthe où vous devez remplacer $referer = $request->get_header('referer')
par $referer = gethostbyaddr($_SERVER['REMOTE_ADDR'])
).
Mais il y a un problème .
Si votre serveur Web se trouve derrière un proxy inverse (solution assez courante, en fait), la connexion TCP au serveur Web est en fait établie par le proxy, ainsi $_SERVER['REMOTE_ADDR']
sera l'IP du proxy, et non l'IP du client qui a initialement envoyé la demande.
Dans de tels cas, l'IP de requête d'origine est généralement disponible en tant que $_SERVER['HTTP_X_FORWARDED_FOR']
, mais être l'une de ces $_SERVER
valeurs qui commencent par HTTP_
n'est pas vraiment fiable.
Donc, si votre serveur Web est derrière un proxy inverse 2, même le $_SERVER['REMOTE_ADDR']
ne serait pas utile pour une telle garde et une liste blanche basée sur le domaine ne pourrait être implémentée qu'au niveau du proxy.
En bref, une solution fiable pour la sécurisation des points de terminaison de l'API doit être implémentée à l'aide d'un mécanisme d'authentification réel (par exemple oAuth) ou doit être effectuée en agissant directement sur la configuration du serveur et non au niveau de l'application.
Remarques
1 Eh bien, en théorie, cela pourrait être cassé si quelqu'un piratait votre FAI ou si un attaquant agissait de l'intérieur de votre réseau local, dans les deux cas, vous ne pouviez pas faire grand-chose pour être en sécurité.
2 Si vous ne savez pas si vous êtes derrière un proxy inverse, vous pouvez envoyer une demande à partir de votre PC local et vérifier si $_SERVER['REMOTE_ADDR']
le serveur correspond à l'IP du PC local et également s'il $_SERVER['HTTP_X_FORWARDED_FOR']
est présent et correspond à l'IP du PC local.