@ssnepenthe\'s aswer 正确的说法是,您使用的钩子不是传入请求中的正确钩子。
PHP可以立即获得请求信息,因此您可以使用可用的最早挂钩来检查它们。如果要在请求API的上下文中执行此操作,则应该使用REST API请求的最早挂钩。\'rest_pre_dispatch\'
根据建议,猪笼草很好,可能还有另一种选择rest_authentication_errors
这将允许您在出现问题时返回错误。
但是Jack Johansson 就在这里saying HTTP头(就像@ssnepenthe的aswer中使用的referer头)是不可信的,因为客户端很容易更改它们。所以,这就像在门前放一个保安,他只会问“让你进去安全吗?”对任何想进去的人来说:那是行不通的。
但是JackJohansson提出的解决方案(nonce)也不是一个真正的解决方案:nonce的全部要点是随着时间的变化而变化,而公共API端点不能有随时间变化的东西。此外,只有当有登录用户时,WP nonce才是可信的,这可能不是公共API的情况,如果用户登录,可能没有理由检查传入的域:您信任用户,而不是用户计算机。
So, what to do?
好吧,即使HTTP头是不可信任的,也不是所有可用的信息
$_SERVER
来自标题。
通常,所有$_SERVER
键以开头的值HTTP_
来自标题,必须视为不安全的用户输入。
但是,例如,$_SERVER[\'REMOTE_ADDR\']
包含用于TCP连接到服务器的IP地址,这意味着is 可信赖的。
这也意味着:
正确配置服务器以生成$_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\'])
).
但是有一个issue.
如果您的Web服务器位于反向代理(实际上是非常常见的解决方案)之后,那么到Web服务器的TCP连接实际上是由代理建立的,所以$_SERVER[\'REMOTE_ADDR\']
将是代理的IP,而不是最初发送请求的客户端的IP。
在这种情况下,原始请求IP通常可用为$_SERVER[\'HTTP_X_FORWARDED_FOR\']
, 但作为其中之一$_SERVER
以开头的值HTTP_
这真的不可信。
因此,如果您的Web服务器位于反向代理之后$_SERVER[\'REMOTE_ADDR\']
对于这样的守卫来说是没有用的,基于域的白名单只能在代理级别实现。
简而言之,API端点安全的可靠解决方案应该使用一些真正的身份验证机制(例如oAuth)来实现,或者应该直接在服务器配置上而不是在应用程序级别上实现。
理论上,如果有人入侵了您的ISP或攻击者从您的局域网内进行攻击,那么它可能会被破坏,在这两种情况下,您几乎无法保证安全。
如果您不知道自己是否支持反向代理,可以从本地PC发送请求,并检查$_SERVER[\'REMOTE_ADDR\']
在服务器上匹配本地PC IP,如果$_SERVER[\'HTTP_X_FORWARDED_FOR\']
存在,并且与本地PC IP匹配。