配置信息防泄露方案:.env 环境隔离详解(dotenv-java)

前言

微服务项目里,数据库密码、大模型 API Key 等敏感信息如果写在 application.properties 并提交到 Git,极易造成泄露。本文介绍一种轻量方案:用 .env 文件 做环境隔离,配合 Java 生态的 dotenv-java 库安全加载配置。

一、需求背景

1.1 硬编码配置的问题

// 反例:配置直接写在代码里

String dbUrl = "jdbc:mysql://localhost:3306/db";

问题 说明
违反开闭原则 改配置就要改代码、重新部署
多人协作冲突 每人本地环境不同,容易互相覆盖
环境切换困难 开发、测试、生产要频繁改代码

1.2 敏感信息暴露的风险

application.properties 中常包含:

  • 数据库账号密码
  • 大模型 API Key
  • OSS 密钥
  • 第三方服务 Token

一旦误提交 Git,后果严重:

风险 说明
安全泄露 公开仓库可被爬取密钥
黑客攻击 密钥被滥用,产生费用或数据泄露
合规风险 金融、医疗等行业有严格安全要求
协作混乱 多人项目应各自维护本地密钥,不能外传

二、解决方案:.env 文件

2.1 什么是 .env 文件?

.env 是一种轻量配置格式,用 KEY=VALUE 键值对存储配置:

  • 将配置与代码分离
  • 集中管理环境变量
  • 跨环境、跨语言通用
  • 语法简单,无需像 .properties 那样转义,也不像 .yaml 那样严格要求缩进

2.2 .env 文件示例

复制代码
# .env 文件内容
DB_URL=jdbc:mysql://localhost:3306/mydb
DB_USER=root
DB_PASS=123456    # 数据库密码(支持注释)
APP_PORT=8080

# AI 相关配置示例
LLM_API_KEY=sk-xxxxxxxxxxxxxxxx
LLM_BASE_URL=https://dashscope.aliyuncs.com/compatible-mode/v1
EMBEDDING_API_KEY=sk-xxxxxxxxxxxxxxxx

2.3 .env 的核心优势

优势 说明
无侵入 独立文件存在,改配置不动代码
跨语言通用 Java、Python、Node.js、Go 都有对应库
关注点分离 配置与业务代码解耦
安全隔离 .env 加入 .gitignore,敏感信息不进版本库

2.4 各语言对应库

语言 库名
Java dotenv-java
Node.js dotenv
Python python-dotenv
Go godotenv

三、Java 实现:dotenv-java 库

3.1 为什么用 dotenv-java?

传统 FileReader 手动读取配置:

  • 要自己处理空格、空行、注释
  • 容易出错
  • 没有类型安全和默认值
  • 缺少必填校验

dotenv-java 可以自动完成这些事。

3.2 Maven 依赖

复制代码
<dependency>
    <groupId>io.github.cdimascio</groupId>
    <artifactId>dotenv-java</artifactId>
    <version>3.0.0</version>
</dependency>

3.3 核心特性

① 环境变量兼容

优先读取系统环境变量,没有再读 .env 文件,方便 Docker/K8s 部署。

② 类型安全与默认值

// 获取配置,不存在时使用默认值

String port = dotenv.get("APP_PORT", "8080");

③ 自动加载

默认从项目根目录加载 .env 文件。

④ 自定义路径
复制代码
// 加载指定环境的配置文件
Dotenv dotenv = Dotenv.configure()
    .directory("./config")
    .filename(".env.dev")
    .load();
⑤ 必填校验
复制代码
// 关键配置缺失时直接报错,防止带病启动
String dbPass = dotenv.get("DB_PASS");
// 或使用 required 强制校验
dotenv.entries().forEach(entry -> {
    // 启动时检查必要配置
});

四、项目目录结构建议

project-root/

├── src/

├── config/

│ ├── .env.dev # 开发环境(不提交 Git)

│ ├── .env.test # 测试环境(不提交 Git)

│ └── .env.prod # 生产环境(不提交 Git)

├── .env.example # 配置模板(提交 Git,无真实密钥)

├── .gitignore # 忽略 .env 文件

└── pom.xml

.gitignore 配置

复制代码
# 忽略所有真实环境配置
.env
.env.*
!.env.example

# 或者精确忽略
config/.env.dev
config/.env.test
config/.env.prod

.env.example 模板(可提交 Git)

复制代码
# 数据库配置
DB_URL=jdbc:mysql://localhost:3306/mydb
DB_USER=your_username
DB_PASS=your_password

# 应用配置
APP_PORT=8080

# AI 大模型配置
LLM_API_KEY=your_api_key_here
LLM_BASE_URL=https://dashscope.aliyuncs.com/compatible-mode/v1
LLM_MODEL=qwen-plus

# Embedding 配置
EMBEDDING_API_KEY=your_embedding_key_here
EMBEDDING_MODEL=text-embedding-v4

# OSS 配置
OSS_ENDPOINT=your_endpoint
OSS_ACCESS_KEY=your_access_key
OSS_SECRET_KEY=your_secret_key

五、与 Spring Boot 集成思路

5.1 加载时机

在 Spring Boot 启动类或配置类中,早于 application.yml 加载 .env,将值注入系统属性或自定义配置源。

5.2 配置优先级建议

系统环境变量(最高)

.env 文件

application-{profile}.yml

application.yml(最低)

5.3 典型使用场景

配置项 存放位置 原因
数据库密码 .env 敏感
大模型 API Key .env 敏感
OSS 密钥 .env 敏感
服务端口 .env 或 yml 环境相关
业务开关 application.yml 非敏感
日志级别 application.yml 非敏感

六、多环境隔离方案

6.1 按环境分文件

环境 文件 部署位置
本地开发 config/.env.dev 开发者本机
测试环境 config/.env.test 测试服务器
生产环境 config/.env.prod 生产服务器

6.2 启动时指定环境

复制代码
# 开发环境
java -jar app.jar --spring.profiles.active=dev

# 通过环境变量指定 dotenv 文件
export DOTENV_FILE=config/.env.prod
java -jar app.jar

6.3 Docker 部署

复制代码
# docker-compose.yml
services:
  app:
    image: my-app:latest
    env_file:
      - config/.env.prod    # 生产配置不入镜像
    ports:
      - "8080:8080"

七、安全最佳实践

实践 说明
.env 永不提交 Git 加入 .gitignore
提供 .env.example 只含字段名和占位符
生产密钥独立管理 每台服务器单独配置
定期轮换密钥 API Key、数据库密码定期更换
最小权限原则 数据库账号只给必要权限
启动时校验必填项 缺关键配置直接失败
日志脱敏 打印配置时屏蔽密码和 Key

八、常见问题

Q1:.env 和 application.yml 有什么区别?

  • .env:放敏感、环境相关配置,不进 Git
  • application.yml:放非敏感、业务相关配置,可进 Git

Q2:团队新人如何知道要配哪些项?

提供 .env.example,README 中说明复制为 .env.dev 并填写。

Q3:生产环境怎么用?

  • 服务器上放 config/.env.prod
  • 或通过 K8s Secret / 云平台密钥管理注入
  • 不要把生产密钥打进 Docker 镜像

Q4:已有 application.yml 还要 .env 吗?

建议敏感项迁到 .env,非敏感项保留在 yml,两者配合使用。

九、知识点总结

要点 内容
核心问题 硬编码配置 + 敏感信息进 Git
解决方案 .env 文件 + dotenv-java
关键原则 配置与代码分离、敏感信息不进版本库
Java 工具 dotenv-java 自动加载、默认值、必填校验
多环境 .env.dev / .env.test / .env.prod
安全实践 .gitignore + .env.example + 密钥轮换
相关推荐
逝水无殇1 小时前
C# 运算符重载详解
开发语言·后端·c#
我才是银古1 小时前
构建 Java GIS 工具库:从碎片化 API 到统一抽象的设计实践
java·gis·geotools·gdal·esri
敲代码的嘎仔2 小时前
实习日志day6--实习日志day6--title命名规范化&businessType纠正&补充缺失的@Log注解&报警与通信模块补充&产出阶段总结文档
java·开发语言·人工智能·git·python·实习·大二
江华森2 小时前
Python 实现高德地图找房(一):环境搭建与数据爬虫
开发语言·爬虫·python
杜子不疼.2 小时前
【Qt初识】信号槽(三):机制意义、断开连接与 Lambda 表达式
开发语言·数据库·qt
编程(变成)小辣鸡2 小时前
Spring事务失效场景
java·后端·spring
极客先躯3 小时前
高级java每日一道面试题-2026年03月30日-实战篇[Docker]-如何监控容器的网络流量?
java·运维·docker·容器·prometheus·高级面试
老迟到的茉莉3 小时前
Hermes 是谁?跟 Claude Code 差在哪
开发语言·python
学逆向的3 小时前
汇编——内存
开发语言·汇编·算法·网络安全