拥有公共 API 但只允许访问从我的网站发送的请求 [英] Having a public API but only allowing access to requests sent from my website

查看:56
本文介绍了拥有公共 API 但只允许访问从我的网站发送的请求的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我已经在 Google 和 SO 上搜索了几个小时,但没有找到与我现在面临的挑战相同的人,所以这里是:

I have been searching on Google and SO for hours now but without finding the someone with the same challenge as I now face so here goes:

我们有一个数据库,我们投入了大量金钱和精力来维护它.数据库中的数据可通过 REST-API 公开获得.我们还有一个使用此 API 的公共 javascript 网络应用程序,我们将其出售给大约 30-40 位客户.由于 API 中的数据对我们来说非常有价值,我们希望尝试保护它,以便没有人可以从中抓取内容并制作自己的数据库副本.我们也不希望任何人使用我们的 API 构建服务未经我们同意.同时,我们需要 http://www.example.com/theApp 上的网络应用程序,http://www.example2.com/theApphttp://www.example3.com/theApp 等以便能够访问 API.没有用户参与.每个人都可以访问 http://www.example.com/theApp 并获得网站的全部功能.API 也是只读的,所以我们不关心任何试图污染我们数据的人.

We have a database with which we put a lot of money and effort into maintaining. The data from the database is publicly available through an REST-API. We also have a public javascript web app that consumes this API and which we sell to some 30-40 customers. As the data in the API is quite valuable to us we want to try to secure it so that no one can scrape the content from it and make their own copy of our database. Nor do we want anyone building services using our API without our consent. At the same time, we need our web app at http://www.example.com/theApp, http://www.example2.com/theApp, http://www.example3.com/theApp etc to be able to access the API. There are no users involved. Everyone can go to http://www.example.com/theApp and get the full feature of the site. The API is also read only so we are not concerned by anyone trying to pollute our data.

javascript web 应用程序是用 react.js 和 node.js 服务器构建的.当然,SSL 将用于服务器和客户端之间的所有通信.

The javascript web app is built with react.js with a node.js server. SSL will, of course, be used for all communication between servers and client.

我认为行不通的事情:

  • 让用户登录以使用 http://www.example.com/theApp.(没有额外的登录功能,所以这只会惹恼用户.)
  • 在网络应用中存储密码/令牌.(javascript 中没有任何东西是安全的,但混淆是安全的.)
  • 使网络应用客户端从身份验证服务器请求令牌.(这个请求也可以由敌对的客户完成.)
  • 将允许的 IP 列入白名单.(每个人都可以访问这些网站...)
  • 将网址列入白名单.(URL 作为标头发送.可以操纵标头.)
  • Making the users log in to use http://www.example.com/theApp. (There are no extra features for logging in so this will just annoy the users.)
  • Storing a password/token in the web app. ( Nothing in javascript is safe however mush obfuscating one does.)
  • Making the web app client request a token from an authentication server. (This request can also be done by hostile clients.)
  • Whitelisting allowed IPs. (Everyone can access the sites...)
  • Whitelisting URLs. (URL is sent as a header. Headers can be manipulated.)

可行的方法(或至少是解决方案的一部分):

  • 让 node.js 服务器应用程序代表客户端从身份验证服务器请求令牌.(但我仍然不知道这将如何防止敌对的客户对 node.js 服务器应用程序的相同请求)
  • 混淆.(这可能会推迟大多数敌对用户,但更持久(和最熟练/最危险?)只会对挑战感到兴奋并最终能够破解它.)

由于这是我们正在努力实现的相当复杂的事情,所以我开始相信这可能是不可能的,如果有人对该怎么做有一些建议,我将不胜感激.如果给出充分的理由,不要这样做"是一个非常好的答案.我更多的是这里的概念性解决方案,但是如果有人想具体讨论软件,我们有一个使用 node.js、Nginx 和 PHP 的 Linux 环境.

As this is quite a complicated thing we are trying to achieve, heck I am starting to believe it might be impossible, I would greatly appreciate if anyone has some advice about what to do. "Don't do it" is a perfectly good answer if good reasons are given. I am more of the conceptual solution here, but if anyone wants to be concrete on software we have a Linux environment with node.js, Nginx and PHP.

推荐答案

如果您不想验证您的用户(您不想让他们登录),您将无法知道谁在使用您的 API,或者什么请求来自哪个用户.发出 API 请求所需的所有信息都已经在 javascript 客户端中,任何人都可以创建另一个客户端,或者向 API 发出有效请求,您甚至无法判断该请求是来自新客户端还是与之前的请求(想要下载您的数据库的人可以在多台客户端计算机上分发下载).

If you don't want to authenticate your users (you don't want them to log in), you have no way to tell who is consuming your API, or what requests come from which user. All the information needed to make an API request is already in the javascript client, anybody can make another client, or a valid request to the API, and you can't even tell if the request is from a new client or the same as in a previous request (somebody that wants to download your database could just distribute downloading across many client computers).

Daniel 的答案可能是您通过这种方式最接近目标的答案.如果您发行代币,则至少可以撤销这些代币.但是,您仍然无法阻止攻击者请求新的请求.

Daniel's answer is probably the closest you can get to your goal this way. If you issue tokens, those at least can be revoked. However, you would still have no way to stop an attacker from requesting a new one.

阅读您的问题后,我的想法是 javascript Web 应用程序可能不是您想要的.您是说您的客户相对较少,而且您根本不想登录.是否可以选择为他们提供桌面/移动客户端之类的东西?它仍然可以是封装在某种容器中的 Javascript,但是对于每个客户端,您可以编译一个包含自己的密钥.一个明显的风险是他们仍然可以提取密钥,但这样一来,不是任何人都可以拥有拥有密钥的客户,事实上,泄漏的密钥将与其合法所有者相关联,并且您可以有合同条款来涵盖这种情况(禁止逆向工程等).您还可以监视和控制数据库的大量下载并撤销有问题的密钥,或实施额外的安全措施,例如限制对某些客户端 IP 地址的密钥访问(如果在您的方案中可能的话).

My thought after reading your question was that a javascript web application is probably not what you want. You are saying you have relatively few clients and you don't want login at all. Would that be an option to give them something like a desktop/mobile client? It could still be Javascript wrapped in some kind of a container, but for each client you could compile one with their own key included. An obvious risk is that they could still extract the key, but this way not anyone could have a client with a key, in fact, a leaked key would be associated with its rightful owner, and you could have contractual clauses to cover that scenario (prohibiting reverse engineering, etc). You could also monitor and control mass-downloads of your database and revoke offending keys, or implement additional security measures like restricting key access to certain client IP addresses if that's possible in your scenario.

当然,这种风险在您的情况下可能会也可能不会被接受,这只是一个想法.显然,从客户端获取密钥很容易,关键是不是每个人都有客户端可以从中获取有效密钥.更好的方法可能是将密钥作为客户端的许可证文件单独分发,它本质上是相同的,但没有硬编码密钥"的概念(我认为在这种情况下它们不是真的).这会让您的生活更轻松,因为您无需在密钥被撤销的情况下分发完整的客户端,只需分发一个新的许可证文件.

This risk of course may or may not be acceptable in your case, just an idea. Obviously, it would be easy to get a key from a client, the point is not everybody would have a client to get a valid key from. A better way would probably be to just distribute keys separately as license files for the client, it's essentially the same, but without the concept of "hard-coded keys" (which I think they are not really in this case). It would make your life easier as you would not need to distribute a full client in case of a revoked key, only a new license file.

这当然是身份验证,但在您的情况下可能对用户更友好,因为用户不需要做任何事情.

This is of course authentication, but in a way that could probably be more user-friendly in your case, as users would not need to do anything.

对于该数量的客户端的另一个想法是客户端证书.对于想要使用您的 API 的任何客户端,您将提供客户端证书.任何人都可以下载您的 Web 应用程序,但客户端证书可用于对 API 的调用者进行身份验证.它与上面的键相同,但处于不同的级别.撤销和发布一个新数据库更困难(并且可能更昂贵),您仍然无法阻止下载整个数据库,但同样,您将有证据证明是谁这样做的,并且可以撤销他们的密钥并将其包含在您的客户端中合同.

Another thought for that number of clients is client certificates. To any client that wants to consume your API, you would give a client certificate. Anyone could download your web app, but client certificates could be used to authenticate callers to the API. It's the same as keys above, but at a different level. It's more difficult (and possibly more expensive) to revoke and issue a new one, and you could still not prevent downloading your whole database, but again, you would have proof who did that, and could revoke their key and cover this in your client contracts.

这篇关于拥有公共 API 但只允许访问从我的网站发送的请求的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆