限制保存在我的数据库中的特定域的 PHP API

Posted

技术标签:

【中文标题】限制保存在我的数据库中的特定域的 PHP API【英文标题】:Restrict PHP API for specific domains which are saved in my database 【发布时间】:2021-05-23 23:48:26 【问题描述】:

我创建了一个 API,它接受主机密钥或 API_KEY,然后验证并返回 JWT 令牌。一切正常,没有 Hostkey 我无法访问受限路由。

问题

主要问题是如果有人将此主机密钥提供给其他人会发生什么,因为它将不再受到保护或将被滥用。所以我想做的不仅是验证主机密钥,还要验证请求来自的域。这是一种付费服务,我真正想限制的是特定域。就像 google 对 MAP Api 所做的那样,就好像我们将该映射键添加到其他域一样,它会引发错误。

【问题讨论】:

AFAIK Google API 仅在您通过 AJAX 调用时描述的方式受到限制。其原因主要是 CORS 限制。如果您从非 AJAX 上下文中调用它们,则不适用。而且它不能适用——“域”在更一般的 HTTP 请求上下文中并不是一个真正的概念。可以从家用计算机向 API 发出请求,并且该计算机不属于任何域,但该请求仍然是合法的 此外,为了进一步与 Google 进行比较,他们通常只使用 API 密钥身份验证来请求已经公开的数据 - 例如公共日历数据等。如果您想访问私人的东西(例如电子邮件),您必须使用更强大的身份验证方法。但最终,无论您使用哪种身份验证系统,如果有人决定故意与其他人共享他们的凭据,那是他们的问题,而不是您的问题。而且你无能为力。 @ADyson 感谢您的回复,但是这个 API 的想法是提供视频服务并在成功认证后在他们的窗口上播放,所以在这种情况下,我们只想在那些域上播放视频允许。否则,如果他们共享他们的 API,那将是我们的损失,因为我们免费提供视频访问。 那么您可以对 Ajax 访问实施 CORS 限制,从而限制对特定域的访问。但目前尚不清楚您的实际视频播放是如何工作的。也许你也可以像 Netflix 那样实现最大并发登录。不清楚您是向网站提供这项服务,还是直接向消费​​者提供这项服务?上下文会影响您的实现方式。 我该如何做 CORS 限制 ajax,因为我卡住的重点是我如何知道我从哪个域获得请求。 【参考方案1】:

执行此操作的唯一方法是检查来源和引荐来源标头。

不幸的是,服务器到服务器这不能可靠地完成,因为引用者和源头将由编码器设置,因此很容易被欺骗。对于服务器到服务器的调用,最好将允许调用 APIS 的 IP 地址列入白名单。在这种情况下,使用 How to get Real IP from Visitor? 之类的东西来获取服务器的真实 IP 并根据白名单 IP 进行验证。

假设这是浏览器中的 JS 调用,而不是服务器到服务器的调用,并且您信任浏览器,那么真正做到这一点的唯一方法是验证引荐来源网址和来源标头。这仍然可以通过浏览器插件甚至像 Postman 这样的工具进行欺骗,因此我不推荐它以提高安全性。这是一个用于验证来源或引用者的 php 示例。

$origin_url = $_SERVER['HTTP_ORIGIN'] ?? $_SERVER['HTTP_REFERER'];
$allowed_origins = ['example.com', 'gagh.biz']; // replace with query for domains.
$request_host = parse_url($origin_url, PHP_URL_HOST);
$host_domain = implode('.', array_slice(explode('.', $request_host), -2));
if (! in_array($host_domain, $allowed_origins, false)) 
    header('HTTP/1.0 403 Forbidden');
    die('You are not allowed to access this.');     

正如@ADyson Cross-Origin Request Headers(CORS) with PHP headers 所评论的那样,CORS 标头也可以选择

【讨论】:

那么其他 API 是如何做到的呢? @Akhilesh 他们使用上述方法的组合来做到这一点。他们可能会按 IP 列入白名单。他们使用 CORS。他们对更有价值的数据使用更强大的身份验证。他们使用诸如限制并发使用之类的缓解措施。我已经向您解释了 Google API 是如何做到的。你似乎认为我们故意不告诉你一些神奇的答案。没有。 @Akhilesh 如果您的项目是一个严肃的项目并且您对此问题有很大的担忧,您应该聘请一位具有 Web 应用程序和 API 经验的安全顾问。然后,当他们比这里更详细地分析了您的所有需求、约束和用例时,您可能会得到一些更定制的建议和路线图。出于必要,在这个志愿者运营的网站中,您往往会得到一般性建议,我们没有时间询问您应用程序的每一个细节,以便为您的确切场景提出创意解决方案。这是你需要做的工作。 @Akhilesh P.S.当然也有非技术性的缓解措施。设置服务条款,明确说明如果用户与他人不当共享凭据或 API 密钥,则可以撤销用户的帐户,并且可以禁止不当使用它们的人使用服务。并以适当的方式为您的内容提供版权/许可,以便滥用它会产生法律后果。这不会阻止所有人,但可能会有所帮助。详情请咨询具有相关经验的律师。 @Akhilesh 可能还有其他一些考虑因素:quora.com/…。我怀疑 Netflix 客户端不仅使用简单的主机密钥对服务器进行身份验证。【参考方案2】:

我想建议对请求数量进行报价或限制,因此当付费 API 达到 100 个请求时,密钥将停止工作,然后付费人不会将密钥提供给其他人。这不是完美的解决方案,但我建议它,因为大多数 API 服务都使用它。

【讨论】:

以上是关于限制保存在我的数据库中的特定域的 PHP API的主要内容,如果未能解决你的问题,请参考以下文章

使用php限制最小订单

我如何只允许特定域的电子邮件在我的微博上注册[关闭]

处理php中的新行

保存大型json数据mongodb

将文本区域的文本保存在数据库中

Node express 服务器,CORS API 限制,包括我的开发机器的 hosts 文件中的一个条目