fix(config): 本地私有配置改用 profile 机制(spring.config.import 优先级不够)
起因:用户把七牛 AK/SK 填进了 application-dev.yml(**会提交的文件**)。 已把密钥挪到 jar 外的 backend/application-local.yml(gitignore), 并把 dev 文件还原成空占位符 —— 确认过待提交差异里没有密钥。 ⚠️ 排查中发现一个**沉默的坑**:一开始用 spring.config.import: optional:file:./application-local.yml 加载本地密钥,结果**启动正常、日志不报错、但配的 provider 完全没生效** (还是本地磁盘)。三步定位: ① 确认 YAML 合法(结构/编码/缩进都对)→ 不是文件问题 ② 换 --spring.config.additional-location=file:./... → **生效了** → 文件与内容没问题,问题在 import 这条路 ③ 把 import 改成**非可选 + 指向不存在的文件** → 启动失败并报 "Config data resource ... does not exist" → 证明 import **确实被处理了**,是**优先级**问题 根因:spring.config.import 导入的文件排在 **profile 文件之后(优先级更低)**, 于是 application-dev.yml 里的 storage.provider 把导入文件里的 provider: qiniu 盖掉了 —— 而这一切没有任何报错。 修法:改用标准机制 —— 文件恢复成 profile 名 application-local.yml, application.yml 里加 spring.profiles.include: local。 profile 文件后加载、优先级更高。启动日志现在打印 The following 2 profiles are active: "local", "dev" 那个坑已写进 application.yml 的注释里,免得后人再踩。 教训:**"配置了但没生效、且不报错"是最难查的一类问题。** 判断某个配置机制到底有没有被执行,有个通用办法: **把它改成一个必然会失败的值** —— 如果照样跑起来,说明它根本没被处理。 ⛔ 仍阻塞:用户填的 AK/SK **验证无效**(七牛 401 bad token)。 两个互相独立的签名实现都失败,所以不是代码问题: ① 七牛官方 SDK 的 Auth.uploadToken(自检走的就是它) ② 手写的管理 API 签名(GET https://rs.qiniu.com/buckets) 线索:AK 40 字符正常、**SK 41 字符**(七牛的 AK/SK 都是 40 字符的 URL 安全 base64); 但逐字符试"去掉首/尾字符"三种组合都被拒 → 不是收尾多一个字符。 需要用户到七牛控制台 → 密钥管理重新完整复制一对。 为不阻塞本地开发,application-local.yml 里 provider 先留 local(密钥保留着, 换成有效的之后去掉一行注释即可)。回归:e2e-m3-file 29/29、m3-submit 31/31。
This commit is contained in:
@@ -61,3 +61,5 @@ backend/data/
|
|||||||
|
|
||||||
# 本地私有配置(云存储密钥等)—— 只提交 .example 模板
|
# 本地私有配置(云存储密钥等)—— 只提交 .example 模板
|
||||||
application-local.yml
|
application-local.yml
|
||||||
|
# 本地私有配置(云存储密钥等)—— 只提交 .example 模板
|
||||||
|
xt-local.yml
|
||||||
|
|||||||
@@ -19,14 +19,15 @@ spring:
|
|||||||
name: xt-server
|
name: xt-server
|
||||||
profiles:
|
profiles:
|
||||||
active: dev
|
active: dev
|
||||||
config:
|
# 额外挂一个 local 配置(backend/application-local.yml,**不提交**)。
|
||||||
# 本地私有配置(**不提交**):放云存储密钥这类不该进仓库的东西。
|
# 用它放云存储密钥这类不该进仓库的东西;文件不存在时是空操作,不影响任何环境。
|
||||||
# optional: 没有这个文件也能正常启动(默认值都在各自的 yml 里)。
|
|
||||||
#
|
#
|
||||||
# ⚠️ 刻意用 file: 前缀(而不是 classpath:)—— 放 classpath 里会被**打进 jar**,
|
# ⚠️ 为什么不用 spring.config.import —— 试过,**优先级不够**:
|
||||||
# 密钥就跟着构建产物到处走了。放在 jar 外面才能保证"构建产物里没有密钥"。
|
# 导入的文件排在 profile 文件之后(优先级更低),于是
|
||||||
# 模板见 backend/application-local.yml.example(那个是提交的)。
|
# application-dev.yml 里的 provider 会把它盖掉,表现是
|
||||||
import: optional:file:./application-local.yml
|
# "文件明明配了 qiniu,启动后却还是本地磁盘",而且不会有任何报错。
|
||||||
|
# profile 文件是后加载的,优先级更高,行为符合直觉。
|
||||||
|
include: local
|
||||||
lifecycle:
|
lifecycle:
|
||||||
# 优雅停机:等在途请求处理完,避免上传/导出被打断
|
# 优雅停机:等在途请求处理完,避免上传/导出被打断
|
||||||
timeout-per-shutdown-phase: 30s
|
timeout-per-shutdown-phase: 30s
|
||||||
|
|||||||
@@ -1196,3 +1196,72 @@ P4 写 M5 校验引擎时,我凭记忆用了一套 VAL 编号,**与 PRD 权
|
|||||||
5. `M1-05` 规则模板
|
5. `M1-05` 规则模板
|
||||||
6. 待办(非阻塞):C1 **小程序资质**(已明确会阻塞学生真正开始填报)、
|
6. 待办(非阻塞):C1 **小程序资质**(已明确会阻塞学生真正开始填报)、
|
||||||
C5 隐私声明法务文案、D1 OCR 引擎选型、D5 一寸照片阈值标定、D6 微信三通道体积上限真机实测
|
C5 隐私声明法务文案、D1 OCR 引擎选型、D5 一寸照片阈值标定、D6 微信三通道体积上限真机实测
|
||||||
|
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## §一·十七 七牛云接入的进展(**阻塞:AK/SK 无效**)
|
||||||
|
|
||||||
|
### ⛔ 当前阻塞
|
||||||
|
用户填的 AK/SK **验证无效**:七牛返回 `401 {"error":"bad token","error_code":"BadToken"}`。
|
||||||
|
**两个互相独立的签名实现都失败**,所以不是某一方的代码问题:
|
||||||
|
1. 七牛官方 SDK 的 `Auth.uploadToken`(走自检,见 `StorageConfig.selfCheck`)
|
||||||
|
2. 手写的**管理 API** 签名(`GET https://rs.qiniu.com/buckets`)
|
||||||
|
|
||||||
|
线索:`access-key` 40 字符(正常),**`secret-key` 41 字符**(七牛的 AK/SK 都是 40 字符
|
||||||
|
的 URL 安全 base64)。但逐字符试「去掉首字符 / 去掉尾字符」三种组合都被拒,
|
||||||
|
说明**不是收尾多一个字符**,多半是复制时中间串了字符。
|
||||||
|
|
||||||
|
**需要的动作(只有用户能做)**:到七牛控制台 → **密钥管理** →
|
||||||
|
重新完整复制一对 AK/SK(SecretKey 需要点「显示」),填进 `backend/application-local.yml`
|
||||||
|
的 `access-key` / `secret-key`,然后把 `# provider: qiniu` 那行的注释去掉,重启,
|
||||||
|
再跑 `python scripts/e2e-m1-storage.py`。
|
||||||
|
|
||||||
|
### ⚠️ 本轮学到的一个"沉默的坑":`spring.config.import` 优先级不够
|
||||||
|
|
||||||
|
一开始用 `spring.config.import: optional:file:./application-local.yml` 加载本地密钥文件,
|
||||||
|
结果**启动正常、日志也不报错,但配的 provider 完全没生效**(还是本地磁盘)。
|
||||||
|
|
||||||
|
做了三步排查才定位:
|
||||||
|
1. 先确认 YAML 本身合法(结构/编码/缩进都对)→ 不是文件的问题
|
||||||
|
2. 换 `--spring.config.additional-location=file:./application-local.yml` → **生效了**
|
||||||
|
(七牛服务构造成功)→ 说明文件与内容都没问题,是 import 这条路的问题
|
||||||
|
3. 把 import 改成**非可选 + 指向不存在的文件** → 启动**失败**并报
|
||||||
|
`Config data resource 'file [x.yml]' ... does not exist`
|
||||||
|
→ 证明 **import 确实被处理了**,是**优先级**问题
|
||||||
|
|
||||||
|
**根因**:`spring.config.import` 导入的文件排在 **profile 文件之后**(优先级更低),
|
||||||
|
于是 `application-dev.yml` 里的 `storage.provider: ${XT_STORAGE_PROVIDER:local}`
|
||||||
|
把导入文件里的 `provider: qiniu` 盖掉了 —— 而这一切**没有任何报错**。
|
||||||
|
|
||||||
|
**修法**:改用标准机制 —— 文件恢复成 profile 名 `application-local.yml`,
|
||||||
|
在 `application.yml` 里 `spring.profiles.include: local`。
|
||||||
|
profile 文件后加载、优先级更高,行为符合直觉。启动日志现在会打印
|
||||||
|
`The following 2 profiles are active: "local", "dev"` ✓
|
||||||
|
|
||||||
|
> 教训:**"配置了但没生效、且不报错"是最难查的一类问题。**
|
||||||
|
> 判断"某个配置机制到底有没有被执行"有一个通用办法:
|
||||||
|
> **把它改成一个必然会失败的值** —— 如果照样跑起来,说明它根本没被处理。
|
||||||
|
|
||||||
|
### 其他已落实的事
|
||||||
|
- `spring.config.import` 的坑已写进 `application.yml` 的注释里(免得后人再踩)
|
||||||
|
- 密钥文件放在 `backend/`(jar 外):`spring.config.import: file:` 那个版本会被打进 jar;
|
||||||
|
现在用 profile 机制,文件在 jar 外,**构建产物里不会有密钥** ✓
|
||||||
|
- `.gitignore` 同时覆盖 `application-local.yml` 与 `xt-local.yml`
|
||||||
|
- 自检脚本 `e2e-m1-storage.py` 的占位符解析已修(原先显示
|
||||||
|
`provider=${XT_STORAGE_PROVIDER:local}`,**配置检查会误报就一文不值**)
|
||||||
|
|
||||||
|
### 当前状态(可用的)
|
||||||
|
- `backend/application-local.yml` 里 **provider 是注释掉的**,所以现在走**本地磁盘** ——
|
||||||
|
填报/上传链路完全正常:`e2e-m3-file 29/29`、`m3-submit 31/31`
|
||||||
|
- 密钥仍在那个文件里留着,等换成有效的,去掉一行注释即可
|
||||||
|
|
||||||
|
### 下一步
|
||||||
|
1. **(用户)换有效的 AK/SK → 去掉 `provider: qiniu` 的注释 → 重启 → 跑自检**
|
||||||
|
2. 自检通过后:`deploy/docker-compose.yml` 里的 MinIO 可以删掉;
|
||||||
|
`XT_STORAGE_PROVIDER=qiniu` 进部署环境变量
|
||||||
|
3. 学生端材料预览(`/mp/files/{id}/url` 已可用,前端未接)
|
||||||
|
4. 直传 `POST /mp/files/upload-token`(有了七牛就能按契约实现;省的是学生那一段上行)
|
||||||
|
5. `M1-05` 规则模板
|
||||||
|
6. 待办(非阻塞):C1 **小程序资质**、C5 隐私声明法务文案、D1 OCR 选型、
|
||||||
|
D5 一寸照片阈值标定、D6 微信三通道体积上限真机实测
|
||||||
|
|||||||
Reference in New Issue
Block a user