@ssnepenthe的aswer说的很对,您使用的钩子不是传入请求中的正确对象。
请求信息可立即用于PHP,因此您可以使用最早的钩子来检查它们。而且,如果要在请求API的上下文中执行此操作,则应使用REST API请求的最早钩子。@ssnepenthe'rest_pre_dispatch'
提出的建议很好,也许另一个选择是允许您在出现问题时返回错误。rest_authentication_errors
但是杰克·约翰森(Jack Johansson)说的对,HTTP标头(例如@ssnepenthe的aswer中使用的引用标头)是不可信的,因为它们很容易被客户端更改。因此,这就像在门前放一个保安,谁会问“可以安全进入?” 对任何想进去的人:那是行不通的。
但是解决方案提出了杰克·约翰逊的答案(随机数)也不是一个真正的解决方案:随机数的全部要点是随时间变化,而公共API终结点不能具有随时间变化的事物。此外,WP nonce仅在有登录用户的情况下才是可信任的(对于公共API可能不是这种情况,并且如果用户已登录,则可能没有理由检查传入域:您信任用户,而不是信任用户)。用户机器。
那么该怎么办?
好吧,即使HTTP标头不可信,也不是所有可用的信息$_SERVER
都来自标头。
通常,所有以$_SERVER
键开头的值HTTP_
都以标头开头,并且必须将其视为不安全的用户输入。
但是,例如,$_SERVER['REMOTE_ADDR']
包含用于与服务器的TCP连接的IP地址,这意味着它是可信任的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'])
)。
但是有一个问题。
如果您的Web服务器位于反向代理(实际上是很常见的解决方案)的后面,则实际上是由代理建立到Web服务器的TCP连接,代理$_SERVER['REMOTE_ADDR']
的IP也将由该IP连接,而不是最初发送请求的客户端的IP。
在这种情况下,原始请求IP通常以形式提供$_SERVER['HTTP_X_FORWARDED_FOR']
,但$_SERVER
以HTTP_
它开头的那些值之一实际上并不可信。
因此,如果您的网络服务器位于反向代理服务器2的后面,即使对于反向$_SERVER['REMOTE_ADDR']
防护2来说也没有用,并且基于域的白名单只能在代理服务器级别实现。
简而言之,应该使用某种真实的身份验证机制(例如oAuth)来实现API端点安全的可靠解决方案,或者应该直接在服务器配置上而不是在应用程序级别执行。
笔记
1好吧,从理论上讲,如果有人入侵了您的ISP或攻击者从您的LAN内部进行攻击,这可能会被破坏,在这两种情况下,您都几乎无济于事。
2如果您不知道自己是否在反向代理后面,则可以从本地PC发送请求,并检查$_SERVER['REMOTE_ADDR']
服务器上是否与本地PC IP匹配,以及是否$_SERVER['HTTP_X_FORWARDED_FOR']
存在并且与本地PC IP匹配。