如何在create-react-app中隐藏API密钥?

J. *_*Kim 25 api github api-key reactjs create-react-app

我在create-react-app中制作了一个天气应用程序.如何隐藏API密钥以便我可以提交给GitHub?

现在关键是在App.js中:const API_KEY ="123456";

ric*_*nae 51

事实证明,create-react-app有一些内置功能可以帮助您实现这一目标.感谢George Karametas的见解.要访问该功能,您需要:

1.创建.env在项目目录的根目录中调用的文件.

- your_project_folder
  - node_modules
  - public
  - src
  - .env         <-- create it here
  - .gitignore
  - package-lock.json
  - package.json
Run Code Online (Sandbox Code Playgroud)

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
Run Code Online (Sandbox Code Playgroud)

3.将.env文件添加到您的.gitignore文件中.

添加下面的行后,保存.gitignore文件并执行a git status以确保您的.env文件不会在git中显示为新文件.

// .gitignore

# api keys
.env       <-- add this line

# dependencies
/node_modules
...
Run Code Online (Sandbox Code Playgroud)

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

要检查您是否可以访问API密钥,请转到您的App.js文件并console.logrequire语句下方添加一个.保存文件并重新加载页面后,如果控制台日志未显示您的API密钥,请尝试重新启动react服务器.在提交代码之前,请务必删除控制台日志行.

// src/App.js

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

console.log(process.env.REACT_APP_WEATHER_API_KEY)

class App extends Component {
...
Run Code Online (Sandbox Code Playgroud)

  • 如果客户端打开devtools,这不会暴露出来吗? (22认同)
  • 我得到一个未定义的。我们必须通过 App.js 文件导入还是必须导出 .env? (3认同)
  • 这绝对是不安全的秘密。.env中的任何内容都可以在开发工具中公开检查。处理此类必须在客户端保持秘密的值的唯一方法是通过将为您处理该值的服务器代理请求。请参阅ClaudiuCreanga对已接受答案的评论。 (2认同)
  • @richardsonae 那么它在生产中是如何工作的呢?生产就绪代码如何知道在哪里访问密钥? (2认同)

이준형*_*이준형 30

详细阐述Arup Rakshit的评论,

首先,你应该在你的src文件夹之外创建.env文件.

然后加

WARNING: Do not store any secrets (such as private API keys) in your React app!

Environment variables are embedded into the build, meaning anyone can view them by inspecting your app's files.
Run Code Online (Sandbox Code Playgroud)

在提交之前,您应该排除此.env文件,以便找到.gitignore文件并添加.env.

现在你可以自由地去.

不要忘记在.gitignore文件中添加.env.


添加:

  1. 如何在代码中使用env变量:

__CODE__

  1. env变量未定义.我如何解决它?

为了读取env变量,您应该重新启动服务器.

  • 这个答案如何?https://facebook.github.io/create-react-app/docs/adding-custom-environment-variables:警告:请勿在React应用程序中存储任何秘密(例如私有API密钥)!环境变量已嵌入到内部版本中,这意味着任何人都可以通过检查应用程序的文件来查看它们。 (34认同)
  • @theprogrammer是的,类似Express服务器那样可以处理请求。那是唯一的方法。 (9认同)
  • @ClaudiuCreanga那么解决方案是什么?是否应该在api键和浏览器请求之间添加节点js服务器?这样,我们的节点服务器是唯一拥有api密钥并使用存储在node js服务器中的api密钥代表用户发出第三方请求的服务器。 (3认同)
  • 您应该重新启动应用程序以更新您的秘密. (2认同)
  • 我认为主要思想不是从你的js服务器获取秘密,而是像代理一样使用你的服务器,当节点服务器使用你的秘密密钥调用外部资源并将所有信息返回到你的前端应用程序时。 (2认同)

Tom*_*rot 21

from the react documentation:

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

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

  • @TrevorWood 是的,将其存储在服务器端并在那里进行实际的 API 调用。后端应该充当 React 应用程序的代理,存储机密、进行 API 调用,然后发回数据。例如,在 React / Express 应用程序中,您可以创建一个 Express 端点来获取天气。您从 React 调用端点,然后 Express 在响应之前使用 API 密钥获取第 3 方天气数据,以便 React 可以显示数据。https://www.rockyourcode.com/secret-keys-in-react (5认同)
  • @TrevorWood 不要将 API 密钥传递给前端,而是将其保存在后端的秘密位置。将其视为一种合作关系,后端执行 API 调用,但前端可以向后端请求数据。请参阅评论:https://hashnode.com/post/should-i-make-3rd-party-api-calls-from-my-frontend-or-the-backend-cizv0ttaz00ats453twjy2ugn (3认同)
  • 那么我们应该做什么呢?将其存储在服务器端?在某些时候,前端需要知道 api 密钥...此时任何人都可以查看它。如果有人知道这方面的好文章,请分享。 (2认同)
  • @AntoniaBlair,但在某些时候前端需要知道去哪里寻找。其他人也会知道去哪里寻找。我觉得这是额外的工作,最终是可以绕过的。 (2认同)
  • 这是如何回答这个问题的? (2认同)

Rog*_*rez 7

这对我有用:

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

 REACT_APP_API_KEY_YT = "key"
//I added YT for youtube which is where my api key is from
Run Code Online (Sandbox Code Playgroud)

然后我去了.gitignore|| 如果您没有,请在根目录中创建.gitignore.在.gitignore中,我添加了.env

 #api key
 .env
Run Code Online (Sandbox Code Playgroud)

然后我回到我的app js文件的根目录.对于我来说,这是其他的index.js,它可能是App.js我创建了一个const API_KEY

 const API_KEY =`${process.env.REACT_APP_API_KEY_YT}`
Run Code Online (Sandbox Code Playgroud)

我检查它是否通过控制台记录它.

 console.log("API", API_KEY)
Run Code Online (Sandbox Code Playgroud)

我得到了undefined.我停止了服务器(Control + C)并重新启动了服务器.之后我才能看到钥匙.

  • 保存.env文件不会像保存.js文件那样导致重新加载react项目。如果对.env文件进行了更改,则需要CMD + C bpm或yarn star,然后重新启动它。 (2认同)

Ant*_*air 6

不幸的是,即使使用gitignore和.env文件,在React客户端中保留任何密钥也不安全。正如@ClaudiuCreanga指出的那样,React环境变量被嵌入在内部版本中,并且可以公开访问。

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

  • 这是正确的答案。在浏览器上运行的客户端应用程序无法安全地存储机密。 (23认同)
  • 这应该是公认的答案。我想知道有多少人由于没有阅读本文并依赖其他人的答案而部署了不安全的应用程序。 (4认同)
  • *所有* API 密钥都必须保密吗?例如,Google Maps API 似乎鼓励在前端使用其 API 密钥。密钥以不同的方式保护,允许开发人员限制允许使用密钥的域并限制可以访问的地图服务。因此,密钥本身并不是秘密,但知道秘密对您没有任何好处,除非您拥有允许使用该密钥的域。 (4认同)
  • 这比其他答案更好,但即使在运行时请求,他们仍然可以查看网络流量并查看 api 密钥是什么,对吧?我的意思是,你可以尝试以某种方式混淆它,但它仍然是同样的问题。据我所知,没有办法在前端应用程序上真正保密 api 密钥。我错了吗? (3认同)
  • @lorweth333,但只有经过身份验证的用户才应允许访问后端。否则都可以打API? (3认同)
  • 但 API 密钥的重点是限制客户端在没有秘密 API 密钥的情况下不能访问后端 API,而你们却说让后端处理它。抱歉我有点困惑。您可以添加更多详细信息吗 (2认同)
  • @techi 理想情况下,在 React 前端应用程序中,用户是提供凭据(用户名/密码)来访问后端(具有身份验证服务的 Node/Express)的人,后端将生成的令牌发回前端以存储在其中内存(未嵌入 HTML/JS 等)。所以现在前端可以告诉后端访问第三方API等。这样我们就可以缓解前端暴露的攻击面,并在后端隐藏第三方API令牌。 (2认同)
  • @devuxer 这是真的,如果 API 密钥被设计为在前端公开/使用,就像您使用 Google Maps Javascript API 的示例一样,那么在那里使用它就可以了。 (2认同)
  • 我正在考虑您在这里提到的相同方式,但我有一个担忧 - 我们需要从客户端发送请求来获取数据。- 任何人都可以发送相同的请求并获取该数据,对吧?- 那么您能告诉我,如何保护/验证从客户端发送的请求吗? (2认同)
  • [React 中的 Firebase](https://www.learnhowtoprogram.com/react-part-time-react-track/react-with-nosql-part-1/adding-firebase-to-react) 演示了一些 API 密钥可以暴露。例如 [Firebase API 密钥可以公开](/sf/ask/2623765651/#37484053)也在不同的问题中回答过。 (2认同)
  • @RVRJ,我一开始也想知道同样的事情,但这些问题来自于没有正确理解安东尼娅的答案。React 应用程序不会从后端获取 api 密钥。它通过充当代理的后端发送请求。只有后端知道密钥,并且只有后端真正与第三方 API 进行通信,因此密钥受到前端的安全保护。 (2认同)

ume*_*mer 6

虽然@Antonia Blair 已经回答了这个问题,但我想更详细地了解一些基本规则。

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

2:Reactjs 只是一个在客户端浏览器中运行您的 javascript 代码的框架。因此客户端可以完全访问 javascript (Reactjs) 代码。客户端没有什么是安全的。因此,永远不要考虑通过将所有代码保留在客户端来使某些内容安全或对客户端隐藏。每当您需要对客户端隐藏某些内容时,您都需要合并服务器端的某些内容。只有服务器端代码对客户端是安全的。

3:所以你要做的是,你将把你的安全密钥保存在服务器端。

假设您的安全密钥的目的是为您的客户制作香蕉。所以客户需要香蕉而不是安全密钥,对吗?所以客户端向服务器请求香蕉,服务器使用安全密钥制作香蕉并将香蕉返回给客户端。毕竟客户来这里只是为了吃香蕉,而不知道我们如何制作香蕉,对吗?

4:所以经验法则是,无论您在何处拥有一些机密数据,都将其保存在服务器上。服务器将使用这些机密数据并将结果数据返回给客户端。

  • 您的方法本身存在安全问题:任何人都可以发布到您的中间件端点,并最终使用您的API来访问示例中的harves API (5认同)
  • @us_david 这就是我想要的,任何人都可以访问我的 API,我将从 Harves API 获取的结果返回给他们。我的 API 对所有人公开。如果我想让我的 API 私有,那么就会出现用户身份验证模块,通过该模块,只有经过身份验证的用户才能向我的 API 发出请求 (5认同)