夜雨聆风学习资料网

ARTICLE · 1038764

【AI+DevOps实战-04】密码别入库_多环境凭据治理

【AI+DevOps实战-04】密码别入库_多环境凭据治理

大家好,我是质量架构师东哥,专注软件研发过程中的质量效率改进。
讲清原理,打通实战,拒绝空谈欢迎关注。

本文承接 【AI+DevOps实战-03】别让AI裸奔_SDD锁住生成一致性,在上一篇中我们已经完成了一个“最简单的”健康检查接口开发,本篇我们讲解项目必备的多环境及账号密码如何管理。同时也响应 constitution 的"凭据治理"条款落地成三环境(dev/test/prod)配置文件体系。核心是两件事:配置怎么组织(双 profile + 环境自包含)和凭据怎么不入库(分层占位策略)。

一、问题背景

1.1 上游若依的原始配置

若依官方 ruoyi-admin/src/main/resources/ 默认长这样:

application.yml          # 主配置:含 Redis、端口、token 等
application-druid.yml    # 单一数据源(明文账号密码!)

问题:

  1. 单 profilespring.profiles.active: druid,没有 dev/test/prod 区分,生产测试共用一份配置。

  2. Redis 写在公共 yml:所有环境共用同一 Redis 地址,无法按环境切换。

  3. 明文凭据application-druid.yml 里 username: root / password: password 明文入库。

1.2 二次开发要解决的矛盾

本项目要同步上游 + 独立部署三环境,配置必须满足:

  • 三环境(dev/test/prod)各有独立的库、Redis、Flyway 开关。

  • 凭据不能明文进 git(constitution 要求"库内 yml 保留示例值")。

  • 本地开发要开箱即用(不能每次 clone 都先配一堆环境变量)。

  • 上游 application.yml 是上游文件,改动要最小化(便于 merge upstream)。

二、方案:双 profile + 环境自包含

2.1 双 profile 机制(业务配置 + 数据源分离)

Spring Boot 的 spring.profiles.active 支持逗号分隔多 profile。我们把业务配置数据源拆成两条线,各自按环境命名:

application.yml             # 主配置:真公共项(端口/上传/token/MyBatis 等)
application-{env}.yml        # 业务差异:Redis + Flyway + 日志
application-druid-{env}.yml  # 数据源:Druid 连接池 + 控制台

启动时用双 profile 激活对应环境:

环境
启动参数
加载的文件
开发
dev,druid-dev
(默认)
application.yml + application-dev.yml + application-druid-dev.yml
测试
test,druid-test
application.yml + application-test.yml + application-druid-test.yml
生产
prod,druid-prod
application.yml + application-prod.yml + application-druid-prod.yml

为什么拆两条线? Druid 数据源配置很长(连接池参数 40+ 行),如果和业务配置混在一个文件,每环境都要复制一大坨。拆开后,application-{env}.yml 只管 Redis/Flyway/日志(环境差异项),application-druid-{env}.yml 管数据源,职责清晰。

2.2 环境自包含法(对齐源项目规范)

关键决策:主 application.yml不放 Redis 和 Flyway——这两项是环境差异项(各环境 Redis 地址/密码、Flyway 开关都不同),由各 application-{env}.yml 各自完整配置。

主 application.yml 只放真正的跨环境公共项

spring:
profiles:
# 本地默认激活开发环境(dev 业务配置 + druid-dev 数据源)
# 测试环境启动用 --spring.profiles.active=test,druid-test
# 生产环境启动用 --spring.profiles.active=prod,druid-prod
active: dev,druid-dev
# 注意:Redis 与 Flyway 为环境差异项(各环境地址/开关不同),
# 不放在本公共文件,由 application-{env}.yml 各自配置,对齐源项目规范
# ...端口、上传、token、MyBatis、xss 等真公共项...

各 application-{env}.yml自包含该环境的 Redis + Flyway:

# application-dev.yml
spring:
data:
redis:
host: 192.168.30.41
password: ${REDIS_PASSWORD:changeme}
flyway:
enabled:false# 开发频繁改 SQL,关掉

2.3 对比:骨架覆盖法 vs 环境自包含法

有两种组织多环境配置的思路,本项目选了后者:

维度
骨架覆盖法
环境自包含法(本项目)
主 yml
含 Redis/Flyway 作"骨架默认值"
只含真公共项,不含 Redis/Flyway
各 env yml
只写差异项覆盖骨架
自包含
完整 Redis+Flyway
优点
env yml 短
看一个 env 文件就懂该环境全貌
缺点
真公共项和环境默认值混在主 yml,难分辨
env yml 有重复(连接池参数三份相同)
源项目
✅ 对齐(源项目主 yml 不含 Redis/Flyway)

环境自包含法的代价是连接池参数在三份 yml 里重复(审查也指出了),可用 spring.config.import 共享 yml 去重,但当前复杂度可接受,先不自证。

三、凭据分层占位策略

3.1 constitution 的凭据条款

memory/constitution.md Security 段:

凭据不入库:数据源、Redis 等连接信息含真实密码时,禁止明文入库。采用 ${ENV_VAR:默认值} 占位。

关键区分:IP 非凭据,可保留明文;密码是凭据,必须环境变量化。

3.2 Spring Boot 占位语法 ${ENV_VAR:默认值}

password: ${DB_PASSWORD:changeme}

含义:优先读环境变量 DB_PASSWORD;未设则用冒号后的默认值 changeme。这样:

  • 部署前 export DB_PASSWORD=真实密码 → 用真实值

  • 不设环境变量 → 用默认值(本地兜底 / 占位符)

3.3 三环境分层策略

不同环境对"默认值"的要求不同,故分层:

环境
默认值策略
理由
dev
真实内网默认值(${REDIS_PASSWORD:123456}
本地友好——clone 即用,不必先 export
testchangeme
 占位符
库内零真实凭据,部署前必须 export,未设则连接失败
prodchangeme
 占位符
同上,生产凭据绝不入库
# application-dev.yml(本地友好)
password: ${REDIS_PASSWORD:123456}# 默认真值,clone 即用

# application-test.yml(占位符)
password: ${REDIS_PASSWORD:changeme}# 必须 export 才能用

# application-prod.yml(占位符)
password: ${REDIS_PASSWORD:changeme}# 必须 export 才能用

dev 为什么保留真值? 这是宪法字面("库内 yml 保留示例值")与用户体验的权衡。dev 环境面向开发者本地,要求每次 clone 都先 export 一堆变量太痛苦;内网开发库密码泄露面可控。test/prod 面向共享环境/生产,凭据必须零入库。审查指出这与 constitution 字面有出入——属已知的设计决策权衡。

3.4 完整占位变量清单

部署 test/prod 前,运维必须 export 这些环境变量:

# 数据源
exportDB_USERNAME=数据库账号
exportDB_PASSWORD=数据库密码

# Redis
exportREDIS_PASSWORD=Redis密码

# Druid 监控控制台
exportDRUID_USERNAME=Druid控制台账号
exportDRUID_PASSWORD=Druid控制台密码

未设任一项,对应服务连接失败(changeme 不是有效凭据)。

3.5 本地覆盖:application-local.yml

若不想用 dev 默认值(比如连自己的本地库),可建 application-local.yml 覆盖,并加进 .gitignore(不入库):

# application-local.yml(加 .gitignore,不入库)
spring:
data:
redis:
password: 我的本地Redis密码
datasource:
druid:
master:
password: 我的本地库密码

启动加 local profile:--spring.profiles.active=local,dev,druid-dev(local 覆盖 dev)。

四、IP 处理:示例化

4.1 IP 是凭据吗

constitution 明确:IP 非凭据。内网 IP 暴露的风险远低于密码——知道了 IP 没有凭据也连不上。所以源项目规范里 IP 可保留明文。

五、文件清单与切换

5.1 最终配置文件结构

ruoyi-admin/src/main/resources/
├── application.yml                    # 主配置(真公共项,不含 Redis/Flyway,active: dev,druid-dev)
├── application-dev.yml                # 开发:Redis(.41 真值) + Flyway 关 + debug 日志
├── application-druid-dev.yml         # 开发数据源(.41/ai-devops,真值兜底)
├── application-test.yml              # 测试:Redis(.130.41) + Flyway 开 + info 日志
├── application-druid-test.yml        # 测试数据源(.130.41,changeme 占位)
├── application-prod.yml              # 生产:Redis(.130.31) + Flyway 开 + info 日志
└── application-druid-prod.yml         # 生产数据源(.130.30,changeme 占位)

上游若依原始 application-druid.yml(单数、明文)已删除,对齐源项目规范——本地默认走 application-druid-dev.yml

5.2 环境切换

后端:改启动参数或 ry.sh

# 本地默认(不指定,用主 yml 的 active: dev,druid-dev)
java-jar ruoyi-admin.jar

# 测试
java-jar-Dspring.profiles.active=test,druid-test ruoyi-admin.jar

# 生产
java-jar-Dspring.profiles.active=prod,druid-prod ruoyi-admin.jar

前端:Vite 环境变量(.env.development/.staging/.production):

yarn dev          # 开发(/dev-api → Vite proxy → localhost:8080)
yarn build:stage  # 测试(/stage-api → Nginx)
yarn build:prod   # 生产(/prod-api → Nginx 负载均衡)

5.3 确认当前环境

启动日志会打印 The following profiles are active: dev,druid-dev,一眼可见。

六、踩坑记录

6.1 Redis/Flyway 放公共 yml 的陷阱

最初把 Redis 和 Flyway 放主 application.yml(当"骨架默认值"),各 env 只覆盖差异。问题:

  • dev/test 的 Redis 同在 .41 但 Flyway 开关不同(dev 关/test 开),用覆盖法要小心"覆盖了地址还是覆盖了开关"。

  • Flyway 在 Spring Boot 4.1.0 移除了自动配置(详见 【AI+DevOps实战-05】Flyway终结数据库变更混乱),spring.flyway.* 没有框架自动绑定,放公共 yml 反而误导(以为改了就生效)。

改环境自包含后,看一个 application-{env}.yml 就懂该环境 Redis + Flyway 全貌,不再有"骨架/覆盖"的隐式依赖。

6.2 changeme 占位符的失败显式

test/prod 用 changeme 而非空字符串作默认值——是有意为之:未设环境变量时让连接失败,而不是静默用空密码连库(可能连上无密码的 Redis)。changeme 是无效凭据,连接会报错,运维能立刻发现没 export。

6.3 删 application-druid.yml 的遗漏

多 profile 重构时,最初只新建了 application-druid-{env}.yml忘了删上游的 application-druid.yml——导致两份数据源配置并存。后补了一个 chore(admin): 删除上游明文 application-druid.yml 提交才对齐源项目规范。提醒:重构删除类操作要单独成提交,别和新增混在一起,容易漏。

七、与 constitution 的对应

constitution 条款
本篇落地
凭据不入库
${ENV_VAR:默认值}
 占位,test/prod 用 changeme
dev 真实默认值 / test-prod changeme
§3.3 分层策略
IP 非凭据可保留明文
§4 IP 示例化(dev 保留真值,其余示例网段)
本地可用 application-local.yml 覆盖
§3.5
Flyway 各环境独立配置
application-{env}.yml 各自配 enabled

八、延伸

  • constitution 凭据条款全文memory/constitution.md Security 段

  • 多环境部署完整文档docs/deploy/多环境部署文档.md(含 Nginx、ry.sh、备份脚本)


下一篇 【AI+DevOps实战-05】Flyway让AI看懂数据库的版本化变更 聚焦 Flyway 在 Spring Boot 4.1 + 若依动态数据源下的手动配置——为什么 spring.flyway.* 不生效,怎么手动绑定主数据源。


如果你觉得这篇文章写的还不错,麻烦双击屏幕点个👍、点个❤️、点个转发,你的支持是我继续分享的动力!

关注公众号回复:ai-devops 获取本系列完整源码。

相关学习资料