spe*_*ith 4 environment-variables node.js express jwt
我对 Node.js 和 Express 比较陌生,我正在遵循使用 JWT 添加身份验证到我的网站的指南:Medium。我对本指南中关于使用秘密的一点感到困惑,它说:
JWT 库在创建和验证令牌时将读取此秘密。在生产中,我们需要将此秘密存储在环境变量中而不是文件中。
在指南中,他们将秘密放在配置文件中。我希望指南描述了为什么 JWT 秘密应该是一个环境变量而不是在配置文件中,但它非常模糊。那么为什么秘密应该是环境变量,以及使用秘密的其他最佳实践是什么?我决定使用 Passport & Express Sessions 代替 JWT 进行身份验证,但我认为它仍然适用于会话密钥。
我的下一个问题是如何在环境变量中准确设置秘密?我不再使用该指南,但是使用它的人如何将该配置文件转换为环境变量?最后,在典型的 Node.js 应用程序中,您通常使用环境变量来做什么?
mat*_*tpr 11
也许最初的问题更多是关于为什么你不应该将秘密硬编码到你的代码库中?希望这对大多数人来说是相当明显的。因此,理想情况下,您的秘密和非秘密“应用程序配置”应该与您的代码库分开,使您的应用程序“可配置”。执行此操作的标准方法:
config.js或) ,因此它永远不会签入。.env.gitignoreconfig.sample.js或sample.env)供新开发人员用作他们自己的开发配置的模板(这是签入的并且不包含真正的秘密)。(是的,我知道这对某些人来说是一个有争议的话题。抱歉。)
您无法真正阻止非特权用户访问 ENV 信息。因此,如果您将机密放入 env 中,攻击者的门槛就会降低,因为他们不一定需要特权帐户来查看在不同用户下运行的应用程序的机密。
如果您要配置生产服务器,您可以使用熟悉的环境变量格式轻松地将机密放入文件中,.env就像 systemd 一样EnvironmentFile。
然而,诀窍是您希望将其视为秘密应用程序加载的配置,而不是将其加载到进程环境(通过 systemd、bash、npm 脚本等)或process.env应用程序中。
dotenv默认情况下(当您调用时.config())填充process.env. 因此,如果您想dotenv安全地使用,您可以使用解析您的.env配置dotenv.parse,这样它就不会将您的秘密.env放入process.env.
这将允许您使用.env生产机密配置文件并使用.env您添加的开发文件.gitignore,这样您就不必提交开发文件。然而应用程序开发人员需要记住使用.parse而不是.config否则存在安全风险。
或者,如果您不想使用dotenv,因为它的主要设计专注于加载 ENV...只需使用导出配置对象的 json 或 js 配置文件(例如config.js)。就像.env您可以拥有未提交的开发版本和自动配置的生产版本一样。这可以在应用程序中需要时需要,并避免意外将机密填充到环境中的风险(使用 dotenv 时)。当然,糟糕的应用程序代码仍然可能会泄露秘密,但至少由于秘密是如何暴露给应用程序的,它们在默认情况下不会被泄露。
所有这一切的缺点是 ENV 为我们提供了一种非常标准的方法来将配置传递给生产环境中任何类型的应用程序/进程/脚本(即不仅仅是 Nodejs)。ENV 不安全意味着我们必须提出一种(理想的标准)机制,将安全配置传递给生产中的各种应用程序和脚本。
在 bash 中(作为示例),您可以获取.env文件,只要这些变量没有被export编辑,它们只是当前 bash 进程的“本地”变量(即不被子进程继承)。不使用export类似于不填充process.env。在简单的 bash 脚本中解析 json 配置...如果没有帮助应用程序,就不那么有趣了。
您希望应用程序开发人员不必考虑生产秘密/配置或安全性,并为他们提供适用于本地开发、测试和生产的标准配置检索机制。
您希望这种标准机制简单明了,并且无意中在应用程序端引发安全问题(将生产秘密暴露给子流程)的风险相对较低。当然,没有什么可以 100% 保护你,就好像应用程序可以访问秘密一样,它可以通过多种方式泄露秘密(写入文件、进行 http 调用等)……但至少不会是由于配置造成的加载/传递机制。
我们目前正在寻找为生产中的各种应用程序解决此问题的选项......如果有人提出深思熟虑的建议或以干净、通用的方式解决此问题的经验,我们将非常高兴。
我倾向于坚持使用,.env因为我们已经支持 EnvironmentFile 配置,并且每个应用程序都可以处理该文件格式(例如可以source使用.envbash)...问题是如何防止应用程序/开发人员意外使用 dotenv.config 而不是dotenv.parse 将其排除在应用程序环境之外。
因此,我们可能只是坚持使用,config.sample.{env,json,js}以便开发团队有一个模板来填充生产秘密。配置由节点应用程序通过 require 加载,因此它不会填充process.env。我们还向我们的应用程序添加命令行标志(或 ENV),以允许指定此配置文件的位置,以便 devops 可以选择将生产配置文件放置在应用程序部署目录之外(这可以使持续部署变得更容易)容易一点)。缺点是 config.js 无法轻松地用于其他语言,但 devops 可以相当轻松地将 ENV 样式变量格式转换为其他目标的脚本。
正如我所说,对 ENV 保密是为了那些关心安全的人。许多在线博客/指南/教程都展示了通过 ENV 的秘密传递。(默认情况dotenv下)将机密加载到流程环境中的流行也可能会让您相信这是正确的方法。安全始终是风险、努力/成本和不便之间的权衡。就我个人而言,我认为如果您自动配置生产,那么解决这个问题并不是什么大问题……问题更多的是提出一种可以跨各种应用程序/代码语言工作的半标准机制。
为什么秘密应该是环境变量,而不是存储在配置文件中?
在处理项目时,您最终会将代码上传到 github,每个人都可以访问。如果您将机密存储在配置文件中,任何拥有 github 帐户的人都可以读取它,因此存在安全风险。将秘密存储为环境变量可确保其安全。您的配置文件应该从对象中读取这些值process.env。像这样的东西:
const jwtSecretKey = process.env.JWT_SECRET_KEY;
const googleApiKey = process.env.GOOGLE_API_KEY;
const serverPort = process.env.PORT || 8000; // 8000 is the default value in case if the env variable has not been set
module.exports = {
jwtSecretKey: jwtSectetKey,
googleApiKey: googleApiKey,
serverPort: serverPort
}
Run Code Online (Sandbox Code Playgroud)
使用这些秘密的任何其他代码都应该需要配置文件。
const config = require('./config');
...
jwt.verify(token, config.jwtSecretKey);
Run Code Online (Sandbox Code Playgroud)
除了将机密存储为环境变量之外,您还应该将任何特定于环境的值存储为环境变量。例如,假设您的 NodeJS 服务器(连接到托管数据库)在三个环境中运行 - 开发、QA 和 PROD。每个环境都将具有有关环境应连接到的数据库主机和端口的不同信息。环境变量是在每个单独的环境上存储数据库主机和端口的好方法,并通过读取环境变量在所有环境中使用相同的代码来连接到不同的数据库。
如何将值存储为环境变量 - 一种方法是手动执行,但我不推荐它。一种方法是使用 shell 脚本。这实际上取决于您的基础设施。
您还应该将 *.env 添加到 .gitignore 文件中,因此将其推送到公共将忽略该文件,并且您只有一个包含所有环境变量的文件。
| 归档时间: |
|
| 查看次数: |
20718 次 |
| 最近记录: |