如何在 create-response-app 中隐藏 API 键?

我在创建-反应-应用程序里做了一个天气应用程序。如何隐藏 API 密钥以便提交到 GitHub?

现在的关键是 App.js: Const API _ KEY = “123456”;

179003 次浏览

警告

除非你正在制作教程应用程序,否则不要在客户端源代码中加入诸如 API 密钥之类的秘密(比如 React 应用程序)。返回文章页面

警告: 不要在您的 应用程序!

环境变量嵌入到构建中,这意味着任何人都可以 通过检查应用程序的文件来查看它们。

首先,创建一个。Env 文件,即在 src 文件夹之外运行 react-scripts start(或 yarn start)。

然后,加

REACT_APP_WEATHER_API_KEY=123456

在提交之前,应该排除这个.env 文件,以便查找.gitignore 文件和 add.env。

变量的名称需要以 REACT_APP_开头,它可以防止您在构建时意外地包含秘密。

别忘了在.gitignore 文件中添加.env。


在代码中使用 env 变量:

const API_KEY = process.env.REACT_APP_WEATHER_API_KEY;

为了在将 env 变量添加到 .env之后读取它们,请重新启动服务器。

免责声明

警告: 不要在您的 应用程序!

环境变量嵌入到构建中,这意味着任何人都可以 通过检查应用程序的文件来查看它们。

下面的答案提供了在环境变量中存储非机密数据的正确方法。请记住,秘密数据可以通过开发人员工具访问,这使得存储为环境变量变得不安全。如果你想存储一些秘密数据,那么存储在后端是更好的选择,如果客户端想访问秘密数据,它可以通过向服务器发出请求来访问。(有关存储秘密数据的更多细节,请参考@Antonia 的答案。)

事实证明,create-response-app 具有一些内置的功能来帮助您实现这一点。谢谢你 George Karametas的洞察力。要访问该功能,您需要:

1. 在项目目录的根目录中创建一个名为 .env的文件。

- your_project_folder
- node_modules
- public
- src
- .env         <-- create it here
- .gitignore
- package-lock.json
- package.json

2. 在 .env文件中,将 REACT_APP_前缀到您选择的 API 密钥名称,并将其分配给它。

create-react-app工具使用 REACT_APP_来识别这些变量。如果不以它作为 API 密钥名的开头,create-react-app就看不到它。

// .env


REACT_APP_API_KEY=your_api_key  <-- yes
API_KEY=your_api_key            <-- no


// Example (from 이준형's response):
REACT_APP_WEATHER_API_KEY=123456

3. 将 .env文件添加到 .gitignore文件中。

添加以下代码行后,保存 .gitignore文件并执行 git status以确保 .env文件不会以新文件的形式出现在 git 中。

// .gitignore


# api keys
.env       <-- add this line


# dependencies
/node_modules
...

4. 通过 process.env对象访问 API 密钥。

要检查是否可以访问 API 密钥,请转到 App.js文件,并在 require语句下面的顶部添加一个 console.log。在保存文件并重新加载页面之后,如果控制台日志没有显示 API 键,请尝试重新启动响应服务器。请确保在提交代码之前删除控制台日志行。

// src/App.js


import React, { Component } from 'react';
import './App.css';


console.log(process.env.REACT_APP_WEATHER_API_KEY)


class App extends Component {
...

以下是对我有效的方法:

我在根文件夹中创建了 .env。 在这个文件夹中,我添加了我的密钥:

 REACT_APP_API_KEY_YT = "key"
//I added YT for youtube which is where my api key is from

然后我转到 .gitignore | | 或者创建一个。根目录中的 gitignore。在里面。我加了吉蒂诺尔。Env

 #api key
.env

然后我回到我的 app js 文件的根目录。对我来说,index.js 对其他人来说,可能是 App.js 在那里我创建了一个 const API _ KEY

 const API_KEY =`${process.env.REACT_APP_API_KEY_YT}`

我通过控制台登录它来检查它是否正常工作。

 console.log("API", API_KEY)

我正在接收 undefined。 我停止了服务器(Control + C)并重新启动了服务器。 后来我看到了钥匙。

从反应 文件:

警告: 不要在你的 React 应用程序中存储任何秘密(比如私有 API 密钥) !

环境变量嵌入到构建中,这意味着任何人都可以 通过检查应用程序的文件来查看它们。

不幸的是,在 React 客户机中保存任何密钥,即使您使用 gitignore 和 .env文件,也是不安全的。正如@ClaudiuCreanga 所指出的,React 环境变量嵌入在构建中,并且是可公开访问的。

应该只在后端(如 Node/Express)中保存 API 密钥或机密。您可以让客户机向后端 API 发送一个请求,然后后端 API 可以使用 API 密钥进行实际的 API 调用,并将数据发送回客户机。

如果将 API 键用于本地开发,请将其放在。开发文件并忽略它。请出示证件。Env 文件将被构建过程拾取,这将在生产环境中公开数据。

详见 https://create-react-app.dev/docs/adding-custom-environment-variables/#what-other-env-files-can-be-used

如上所述,创建一个 .env文件是很有帮助的

- 如果你使用 API_KEY在你的 网址作为 state像这样-

this.state = {
url:`http://newsapi.org/v2/everything&apiKey=${process.env.REACT_APP_API_KEY}`
}

然后它将在反应开发工具中可见。

相反,你可以把你的 API_KEY直接放在 捡回来的位置

fetch(`http://newsapi.org/v2/everything?&apiKey=${process.env.REACT_APP_API_KEY}`)

尽管@Antonia Blair 已经回答了这个问题,但是我还是想通过一些基本的规则来说明一些问题。

1: 大多数答案都建议使用。Env 文件。我想把话说清楚。Env 没有添加任何安全层.那个。正如名称所描述的那样,env 只是在构建时设置环境。例如,通过使用环境变量,您可以在构建时设置一些全局值,并且可以在运行时访问应用程序中的这些值。

Reactjs 只是一个在客户端浏览器中运行 javascript 代码的框架。因此客户端可以完全访问 javascript (Reactjs)代码。客户端没有什么是安全的。因此,永远不要想着通过保持所有代码都在客户端来保证某些东西的安全性或者对客户端进行隐藏。无论何时您需要向客户机隐藏某些内容,都需要在服务器端合并某些内容。只有服务器端代码在客户端是安全的。

他说: 所以你要做的是,把安全密钥放在服务器端。

假设您的安全密钥的目的是为您的客户端制作一个 cookie。所以客户需要的是 cookie 而不是安全密钥,对吧?因此客户端向服务器请求一个 cookie,服务器使用安全密钥生成 cookie 并将 cookie 返回给客户端。毕竟客户来这里只是为了吃饼干而不是知道我们怎么做饼干,对吗?

他说: 所以经验法则是,无论你在哪里有机密数据,你都要把它保存在服务器上。服务器将使用此机密数据并返回要公开给客户端的结果数据。

编辑 Sep _ 06 _ 2021

一个用户要求一个编码示例,所以我将提出一个实时场景,我已经处理使用上述技术。 这是我的用例

  1. 我有一个 Reactjs 应用程序,它提交一个公共形式的非公共 API。

  2. 非公共 API 是由 Https://www.greenhouse.io/

  3. 这个 API 需要一个身份验证头来使用它发出请求。我已经向 API 所有者订阅了 API,并且从他们那里收到了一个秘密令牌,我可以使用这个令牌来访问他们的 API

  4. 当然,我想保持我的信物个人,不暴露给 公众使用者

  5. 我已经使用了 Axios 客户机来与 API 进行通信

我有两种方法来执行上述场景

错误的方法

我直接从 Reactjs 应用程序向 API 发出请求

假设下面是我想要访问的 API 端点

apiURL=https://boardsapi.greenhouse.io/v1/boards/xyz/jobs/"+jobId+""

上述 API 端点需要一个授权头,我将在其中提供我的秘密令牌。

const config = {
headers: {
"Authorization": "Basic ####MySecretCode#####",
} };

假设我想用这个请求发布一些表单数据

let formData=MyFormData

现在,我可以使用如下的 Axios 客户机发送我的请求

  let result=await axios.post(apiURL, formData,config);

使用上述技术,我可以成功地将表单数据发布到 HarvestAPI。

但是就像我说的,它是一个 错误的方式来与这个 API 进行通信。因为我在客户端暴露了我的秘密令牌。

正确的方式

我在 Nodejs 上构建了一个 API 并公开托管它。

假设我想向 HarvestAPI 发布一些表单数据

let formData=MyFormData

我不会直接从我的客户端应用程序访问 Harvest API。相反,我在中间件 API 中公开了端点来处理这个问题。 让我们说下面是我想点击的中间件 API 的端点 URL

apiURL=https://proxy-server/apply

上述 API 端点不需要授权标头。因此,我可以使用如下的 Axios 客户机发送一个帖子请求

let result=await axios.post(apiURL, formData);

区别很明显。在我的要求中,这次我没有提供秘密令牌。因为这不是对 Harvest API 的直接请求,而是对我开发并托管的中间件 API 的请求。

我在我的中间件 API 中接收这个请求,将我的秘密令牌添加到它,并将其转发到 Harvest API。来自 Harvest API 的响应被返回到我们的中间件 API,并因此转发回到我们的 Reactjs 客户机应用程序。

秘密令牌现在驻留在我的服务器端 API 中,不会被外部用户使用。

下面是一个在代码中找到 API 密钥的例子,即使你试图把它隐藏在一个环境变量中。

我使用 NewsAPI 构建了一个非常简单的应用程序,它要求我注册一个 API 密钥。以下是我使用 API 键作为环境变量对 NewsAPI 端点的获取。

fetch(`https://newsapi.org/v2/top-headlines?q=${keyword}&apiKey=${process.env.REACT_APP_API_KEY}`)
.then(res => res.json())
.then(
(result) => {
setIsLoaded(true);
setArticles(result.articles);
})

但是,当我使用 Chrome dev 工具检查网络请求时,您将能够看到 API 键的实际值。我希望这能帮助人们了解如何在客户端上找到一个 API 密钥,即使你把它存储为一个环境变量。

inspecting API keys in network request

编辑解释 怎么做可以隐藏一个 API 密钥: 您可以从服务器端逻辑发出 HTTP 请求,这样就可以安全地将 API 密钥隐藏在。Env 文件。在下面的例子中,我创建了一个/top-header/: searchTerm 的端点。一旦接收到对该端点的请求,我就使用“ NEWS _ API _ KEY”环境变量将 axios 请求发送到 NEWS API。Env 文件。

route.get("/top-headlines/:searchTerm", async (req, res) => {
const { searchTerm } = req.params;
    

try {
const articlesResponse = await axios.get(
`https://newsapi.org/v2/top-headlines?q=${searchTerm}&apiKey=${process.env.NEWS_API_KEY}`
);
    

const articlesData = articlesResponse.data;
    

res.send(articlesData);
} catch (error) {
console.log(error);
}
});

安全密钥/机密永远不应该发送到客户端。假设,您想通过应用程序(在浏览器中运行)从客户端机器上的 S3下载一个文件。

  • 调用服务器以获取临时令牌(随时间过期)

  • 服务器(具有机密和所有内容)生成令牌并将其发送回来

  • 客户端使用令牌访问 S3

令牌本身不是秘密,一旦过期就没用了。

请注意! ,如果在 React 客户机中放置任何凭据,即使使用 gitignore 和 an。Env 文件,仍然不安全。

应该只在后端(如 Node/Express)中保存 API 密钥或机密。使用代理服务器,从前端向后端发送请求,然后后端向前端发出获取数据的请求。

如果你是在生产,那么你不能使用 env 变量直接在那里为前端(反应)。如果您想在生产环境中访问 env 变量,那么您需要遵循这个链接 https://www.freecodecamp.org/news/how-to-implement-runtime-environment-variables-with-create-react-app-docker-and-nginx-7f9d42a91d70/中的说明来实现这个目标。