12k
All articles

.env 文件与不提交机密信息的艺术

将 API 密钥和数据库凭据存储在 env 文件中,通过 Node.js 的 dotenv 加载,并将机密信息排除在版本控制之外。

OpenReplay Team
OpenReplay Team
.env 文件与不提交机密信息的艺术

您是否曾在项目中看到 .env 文件并好奇它的用途?或者您是否听说过意外将 API 密钥提交到 GitHub 的危险?本指南将解释您需要了解的关于 .env 文件的一切——它们是什么、为什么重要,以及如何正确使用它们来保护您的机密信息。

关键要点

  • .env 文件将环境特定的配置和机密信息与您的代码分开存储
  • 永远不要将 .env 文件提交到版本控制系统
  • 使用 .env.example 文件来记录所需变量,而不暴露实际值
  • 在应用程序启动时验证环境变量
  • 随着团队和应用程序的增长,考虑更高级的解决方案

什么是 .env 文件?

.env 文件是一个简单的文本文件,以 KEY=value 格式存储环境变量。这些文件有一个关键目的:将敏感的配置数据与您的代码分离。

# 示例 .env 文件
API_KEY=a1b2c3d4e5f6g7h8i9j0
DATABASE_URL=postgres://username:password@localhost:5432/mydb
DEBUG=false

环境变量是可以影响运行中应用程序行为的值。通过将它们存储在 .env 文件中而不是在应用程序中硬编码,您可以获得几个优势:

  1. 安全性:敏感数据不会出现在您的代码库中
  2. 灵活性:不同的环境可以使用不同的配置
  3. 简单性:易于更新而无需更改代码

为什么存在 .env 文件:简史

.env 文件方法在 2012 年左右作为 十二要素应用 方法论的一部分而流行,该方法论建议将配置存储在环境中。在这种标准化之前,开发人员经常犯危险的错误:

  • 直接在代码中硬编码数据库凭据
  • 将 API 密钥存储在已提交的配置文件中
  • 在不同环境中使用不同的配置机制

这些做法导致了严重的安全漏洞。2016 年,Uber 遭受了大规模数据泄露,暴露了 5700 万用户的数据,因为开发人员在 GitHub 仓库中发布了 AWS 凭据。和解费用达 1.48 亿美元。

.env 文件的工作原理

.env 文件在概念上很简单,但在实践中很强大。它们通常的工作方式如下:

  1. 您在项目根目录创建一个 .env 文件
  2. 您以 KEY=value 格式添加环境特定的变量
  3. 应用程序中的库在运行时加载这些变量
  4. 您的应用程序代码通过环境变量访问这些值

最重要的部分:您的 .env 文件永远不应该提交到版本控制系统

在 Node.js 项目中设置 .env 文件

让我们通过一个使用 Node.js 的实际示例来演示:

1. 创建 .env 文件

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

# API 凭据
API_KEY=your_secret_api_key
API_SECRET=your_secret_api_secret

# 数据库配置
DB_HOST=localhost
DB_USER=root
DB_PASS=password
DB_NAME=myapp

# 应用程序设置
PORT=3000
NODE_ENV=development

2. 将 .env 添加到 .gitignore

创建或更新您的 .gitignore 文件以包含:

# 环境变量
.env
.env.local
.env.*.local

3. 安装 dotenv 包

npm install dotenv --save

4. 在应用程序中加载环境变量

在主应用程序文件的最顶部(在任何其他代码之前):

require('dotenv').config();

// 现在您可以使用 process.env 访问变量
const apiKey = process.env.API_KEY;
const port = process.env.PORT || 3000;

console.log(`在端口 ${port} 上启动服务器`);

安全最佳实践

遵循这些最佳实践将帮助您避免常见的安全陷阱:

1. 永远不要将 .env 文件提交到版本控制

这是最重要的规则。检查您的 .gitignore 文件以确保排除了 .env

2. 创建模板 .env.example 文件

提供一个包含所需变量但不包含实际值的模板:

# API 凭据
API_KEY=
API_SECRET=

# 数据库配置
DB_HOST=
DB_USER=
DB_PASS=
DB_NAME=

# 应用程序设置
PORT=3000
NODE_ENV=development

这个文件应该提交到您的仓库,以帮助其他开发人员知道他们需要设置哪些变量。

3. 验证所需的环境变量

在应用程序启动时检查所有必需的变量是否存在:

const requiredEnvVars = ['API_KEY', 'DB_HOST', 'DB_USER', 'DB_PASS'];
const missingEnvVars = requiredEnvVars.filter(
  envVar => !process.env[envVar]
);

if (missingEnvVars.length > 0) {
  throw new Error(`缺少必需的环境变量: ${missingEnvVars.join(', ')}`);
}

4. 为不同环境使用不同的 .env 文件

对于更复杂的设置,您可能需要多个环境文件:

  • .env.development - 开发环境设置
  • .env.test - 测试环境设置
  • .env.production - 生产环境设置

常见挑战和解决方案

挑战:在团队成员之间共享机密信息

在团队成员之间安全地共享机密信息是棘手的。避免通过电子邮件或聊天发送凭据。

解决方案:

  • 使用具有共享功能的密码管理器
  • 考虑使用机密管理服务,如 DopplerHashiCorp Vault
  • 对于小团队,安全的加密渠道可能是可以接受的

挑战:管理多个环境

随着应用程序的增长,您需要跨环境管理变量。

解决方案:

  • 使用环境特定的 .env 文件(.env.development.env.production
  • 实现加载层次结构,其中 .env.local 覆盖 .env
  • 对于较大的团队,考虑环境变量管理工具

挑战:CI/CD 流水线集成

您的 CI/CD 流水线需要访问机密信息,但您不能提交 .env 文件。

解决方案:

  • 使用您的 CI/CD 提供商的机密管理(GitHub Secrets、GitLab CI/CD Variables)
  • 与机密管理服务集成
  • 在部署期间从安全源生成 .env 文件

超越基本用法

使用 TypeScript

对于 TypeScript 项目,您可以为环境变量添加类型安全:

// src/env.d.ts
declare namespace NodeJS {
  interface ProcessEnv {
    NODE_ENV: 'development' | 'production' | 'test';
    PORT: string;
    API_KEY: string;
    // 在这里添加其他变量
  }
}

Docker 和容器化

使用 Docker 时,您有几种处理环境变量的选项:

  1. 使用 --env-file 标志:

    docker run --env-file .env myapp
  2. 在您的 docker-compose.yml 中定义变量:

    services:
      app:
        image: myapp
        env_file:
          - .env

.env 文件的替代方案

虽然 .env 文件很流行,但它们不是唯一的解决方案:

方法优点缺点
.env 文件简单,广泛支持手动共享,无版本控制
环境变量原生操作系统支持,无需文件更难管理变量集
配置服务器集中化,版本化,访问控制设置更复杂,潜在单点故障
机密管理器安全,审计,访问控制成本,额外依赖

常见问题

我可以在 .env 文件中使用注释吗?

可以,注释以 # 开头。

.env 和系统环境变量有什么区别?

.env 文件在运行时由您的应用程序加载,而系统环境变量在操作系统级别设置。.env 变量只影响加载它们的特定应用程序。

如何处理多个环境?

使用环境特定的文件,如 .env.development 和 .env.production,或使用机密管理服务。

.env 文件有性能问题吗?

对于大多数应用程序,影响可以忽略不计。文件通常在启动时只读取一次。

与团队共享 .env 文件的最佳方式是什么?

使用安全的密码管理器或专用的机密管理工具,而不是电子邮件或聊天。

结论

通过使用 .env 文件将机密信息保持在代码库之外,您正在朝着更安全的应用程序开发迈出重要一步。记住:最安全的机密是永远不离开您本地环境的机密。

Listen to your bugs 🧘, with OpenReplay

See how users use your app and resolve issues fast.
Loved by thousands of developers

We use cookies to improve your experience. By using our site, you accept cookies.