【问题标题】:Where to store API key in ReactJS?在 ReactJS 中存储 API 密钥的位置?
【发布时间】:2021-10-06 20:36:46
【问题描述】:

我快速提问!

我有一个只从 API 获取数据的 web 应用程序,所以我没有后端部分。我的问题是您将 API 密钥保存在哪里?根据 React 文档,您不应该在应用程序中存储 API 密钥,那么当您有一个使用 API 的 Web 应用程序并且您必须在获取请求中使用 API 密钥时,您如何管理它?

【问题讨论】:

  • 同样的问题困扰着 google maps api。完整的客户端脚本公开公开 api 密钥。在这种特殊情况下,谷歌建议结合其他功能限制密钥,例如限制哪个域可以访问它。您的 API 服务提供商是否提供域限制?
  • 哦,好的!嗯,我真的不知道他们在文档中是否有域限制。我使用的api是developers.themoviedb.org
  • 我明白了。这可以追溯到 2016 年,但仍然很有趣:themoviedb.org/talk/582744abc3a3683601019dcc
  • 这是 2014 年的,更长的线程:themoviedb.org/talk/52c61af419c2952ac805bc31

标签: javascript reactjs


【解决方案1】:

更多的是建议他们将您的 API 密钥保留在服务器端,并让您的 Web 应用程序与您的服务器进行通信。否则恶意用户很容易窃取您的 API 密钥并将其用于任何目的。

如果你认为如果你的密钥被泄露(从头开始,)不会有太大的安全风险,那很好,你可以把它保存在你的 web 应用程序中。真的取决于您的用例以及该 API 密钥的用途。

【讨论】:

  • O.P.已经声明他们没有服务器端部分(他们称之为“后端”)
  • @GrafiCode 这就是为什么我的问题的前半部分谈到它是一个建议(它仍然是一个很好的做法)以及为什么会这样,而后半部分提到如何仍然可以在你的应用程序中保留密钥完成。
【解决方案2】:

创建一个 dotenv 文件并存储所有密钥和 API 密钥。确保在每个变量之前使用 REACT_APP_

文档:https://create-react-app.dev/docs/adding-custom-environment-variables/ dotenv 包:https://www.npmjs.com/package/dotenv

【讨论】:

    【解决方案3】:

    让我们做一些解释,这样您就可以将这些点连接起来并进行更稳健的设计。最后有两(三)个地方存放它:

    1. 前端(您的 React 应用程序)
    2. 后端(您的服务器)
    3. 第三方服务

    TL;DR:对注册用户使用非前端解决方案 + 速率限制,并妥善保护注册步骤(+验证码)。


    1. 前端

    在前端存储任何东西都是一个坏主意,除非你完全确定你可以允许这些数据被暴露——常量、名称、图标,也许是一些 URL,所以你没有在 JS 中硬编码文件。

    您的“编译”ReactJS(或任何其他框架)在构建时只是一个稍微损坏(缩小/转译/等)的 JavaScript,但要使其正常工作,客户端必须检索它并在浏览器中执行它。因此,在 ReactJS 应用程序启动之前,有 1+ 个请求下载 JavaScript 代码和应用程​​序的其他部分,具体取决于框架。

    您可以在任何现代浏览器的网络监控选项卡中看到这些,或者简单地使用 Wireshark(除非加密,那么它有点烦人)或使用不太健全的浏览器的本地代理。

    检索后,如果您自己不知道如何操作,您可以简单地尝试 Ctrl+F 或任何在线 deminifier/deobfuscator 并且您可以检索密钥。

    检索时的含义

    • 我可以冒充你提供颁发 API 密钥的服务
    • 我可以通过频繁调用来锁定您的密钥/帐户(只是为了好玩或检索一些信息)
    • 我可以使用您的网络进行抓取,而无需支付 API 密钥(如果已支付)或向此类服务供应商注册
    • 如果它是每个请求的 API 密钥,并且有一些限制会导致您花钱,我可以通过服务运行一些愚蠢的 while (true) { callYourApi() } 让我匿名,只是为了让您花钱

    根据 API 密钥和您打算解决此问题的严重程度,您可以将 .env 文件仅用于开发目的。尽管您永远不应该在前端存储 API 密钥,除非您明确必须将其存储在其中(例如地图),因为这通常是一个非常愚蠢的想法,并且允许任何人滥用它。

    1. 后端

    如果正确配置和保护您的服务器,您的服务器会将密钥存储在无法通过简单的路径遍历(如果在文件中)或抓取(如果您尝试检索密钥以在前端部分执行)无法访问的任何地方。

    因此,最明智和最安全的方法是通过自定义 API 或计划脚本收集数据来检索(任何服务的)数据,当您的前端被调用时,它们将能够以预渲染的形式检索或者已经获取,因此这种情况不需要密钥。

    但是!这是有窍门的。如果您将自定义 API 设计为 /api/<key>=123/api/<param> 并使用原始 API 的该参数在前端进行过滤,则攻击者不会关心 API 密钥,因为您已经免费创建了一个 API,并且使其公开且不安全。

    所以GET /yourapi/<my data> 和 API 密钥是免费的,甚至不需要显示。

    如何安全地做到这一点?两种简单的方法:

    将数据预渲染为 HTML

    然后您使用前端获取并仅显示 - 但这个可以被刮掉,如果更复杂,它会有点烦人,但就是这样。服务器端渲染听起来不错,但实际上不适用于这种情况。它应该主要用于使前端快速或模板化视图,但从不作为银弹解决方案出于安全目的(因为它不能那样工作)。

    速率限制 + CORS + 账户管理

    通过速率限制,您可以确保用户(最好只有在用户登录后才调用该 API)只能调用该 API,例如1 小时内 10 次,使用 CORS,您可以确保它只能由您的前端调用。

    这也不是灵丹妙药,任何有一点脑子的人都可以简单地在本地抓取您的 API 从而绕过 CORS,但是如果您禁止从单个 IP 注册超过 1 个用户或如果您需要电话号码进行验证。并添加一些烦人的验证码,因此对某些人来说自动化是有问题的。

    它仍然可能被攻击和滥用,但它痛苦,除非您允许多次使用相同的电话号码(或任何其他不太容易获得/需要努力获得的 ID),所以它会让最不称职的人离开……而其余的人,好吧,无论如何他们都会玩你的网站,所以如果你单独维护它,请进行适当的安全评估/强化你的服务器。

    1. 第三方

    类似于 2.,但您不维护“低级”服务器部分,因为第三方正在为您管理它,您只需要指定调用它的条件。这适用于 FirebaseSupabase ,它们的行为类似于单独的后端,但可以有多个模块(对于 FB,12)。

    因此,您将使用 Firebase functions(或其他替代方法),您将在其中拥有您的密钥,例如即使是硬编码,客户端(浏览器)也无法访问它,添加一个限制、cors,也许是一些用户注册限制,你就完成了。


    注意:任何域、IP、地区、电话号码限制都可以绕过,所以不要依赖它们。这只是在将您的网站误用于与您预期不同的事情时需要付出努力的一种手段。

    • 域:curl http(s)://yourweb/path -H "Host: spoofed-domain"
    • 地区或 IP:代理、VPN、Tor、I2P,只是别人的计算机/服务器 + ssh,一些随机 WiFi
    • 电话号码:如果我想可以去当地商店买10个新鲜的

    【讨论】:

    • 哇!这是一个很好的答案!非常感谢您花时间解释!
    【解决方案4】:

    在不暴露您的客户端应用程序中的 API 密钥的情况下执行此操作的唯一方法是创建一个后端并从后端应用程序提供客户端应用程序,如上面 Kelvin Schoofs 和 Peter Badida 的回答所述(或使用第三方服务,例如作为 AWS 凭证保险库)。我建议你使用 Node Express 库作为后端,因为它会为你处理很多样板代码。网上有很多这方面的教程。

    按照其他一些用户的建议使用 dotenv 文件只会将您的 API 代码隐藏在 Git 等版本共享工具中(因为您可以忽略 gitignore 中的 dotenv)。了解 dotenv 与 React 应用程序的过程非常重要。任何在浏览器中打开开发控制台的用户都可以在静态 HTML 中查看您公开的 API 密钥。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2017-10-22
      • 2023-02-10
      • 2017-04-10
      • 2010-11-09
      • 2020-04-05
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多