83 lines
5.0 KiB
Markdown
83 lines
5.0 KiB
Markdown
# 数字我 / Digital Me — 生产环境配置 Checklist
|
||
|
||
> 逐项对照 `digital-me-backend/.env`。分四档:🔴 不设=有洞/起不来 · 🟠 强烈建议 · 🟡 按功能可选 · ⚪ 可留默认。
|
||
|
||
---
|
||
|
||
## 🔴 0. 总开关(漏了这个,前面所有安全修复都白做)
|
||
|
||
- [ ] **`NODE_ENV=production`**
|
||
这是本次安全修复的**总开关**。不设它(默认 development)会导致:
|
||
- 忘记密码 / 短信验证码 **明文回传**(任意账户可被接管)
|
||
- 商店 stub 通道 **免支付开通 + 冒充登录**
|
||
- 微信 `mock-scan` 后门 **开着**
|
||
- `assertProdConfig` 直接跳过 → **默认 JWT 密钥都不会被拦**
|
||
|
||
> 部署后务必确认进程真的读到了 `production`:启动日志应是 `on :3701 (production)`。
|
||
|
||
## 🔴 1. 起不来 / 必设
|
||
|
||
- [ ] **`JWT_SECRET`** = 强随机值(≠ `change-me-in-prod`)。生产下不设,服务**拒绝启动**(fail-fast,符合预期)。
|
||
生成:`openssl rand -hex 32` 或 `node -e "console.log(require('crypto').randomBytes(32).toString('hex'))"`
|
||
- [ ] **`MONGO_URI`** = 你的生产 Mongo(默认 `mongodb://localhost:27017` 仅本机可用)。
|
||
- [ ] **`MONGO_DB`** = `digital_me`(独立库,别和别的产品共用)。
|
||
- [ ] **`CORS_ORIGINS`** = 前端真实域名(如 `https://digitalme.invoratec.cn`)。不对会导致前端跨域被拦。
|
||
- [ ] **`PUBLIC_URL`** = 本 API 的公网地址(如 `https://digitalme-api.invoratec.cn`)。捏脸/口播视频靠它被 DashScope 回拉素材,必须公网可达。
|
||
|
||
## 🟠 2. 强烈建议(安全 / 生产质量)
|
||
|
||
- [ ] **`DATA_ENC_KEY`** = 任意强随机串。不设 → 访客聊天记录**明文入库**(`assertProdConfig` 只 warn 不拦)。
|
||
- [ ] **`SUPER_ADMIN_EMAILS`** = 你的邮箱(逗号分隔)。不设 → 没人能授予蓝V认证 / 进后台。
|
||
- [ ] **`TRUST_PROXY`** = 生产默认自动 on;若**不在** nginx/cloudflare 后面才需显式 `false`(否则限流按错 IP)。
|
||
- [ ] **`MAX_QUESTION_LEN`** = 默认 2000,按成本/滥用容忍度调。
|
||
- [ ] **`MODERATION_MODE` / `MODERATION_URL`**:默认只有内置正则兜底。接专业内容安全服务(`MODERATION_URL`)或 `MODERATION_MODE=llm` 更稳(live 视频对话现在也走审核了)。
|
||
|
||
## 🟡 3. 按功能可选(不配=优雅降级,不会崩)
|
||
|
||
| 功能 | 需要的 env | 不配的表现 |
|
||
|---|---|---|
|
||
| AI 聊天 / 知识 RAG | `DASHSCOPE_API_KEY` | 聊天 → 502;其余正常 |
|
||
| Claude 兜底 | `ANTHROPIC_API_KEY` | Qwen 挂了没有兜底 |
|
||
| 捏脸(万相) | `AVATAR_PROVIDER=dashscope` + 公网 `PUBLIC_URL` | 用上传原图(往往更像本人,OK) |
|
||
| 声音克隆 / TTS | `DASHSCOPE_API_KEY` | `voice-not-cloned` |
|
||
| 口播视频(EMO) | `DASHSCOPE_API_KEY` + 公网 `PUBLIC_URL` | 不可用 |
|
||
| 英文原生发音 | `AZURE_SPEECH_KEY` | 回退克隆音色/浏览器 TTS |
|
||
| 手机短信登录 | `SMS_PROVIDER=aliyun` + `ALIYUN_SMS_*` | 生产下**直接不可用**(已 fail-closed,不再泄露验证码)※ |
|
||
| 邮箱找回密码 | `EMAIL_PROVIDER=<非stub>` + 实现 `sendEmail` | 生产下**直接不可用**(已 fail-closed)※ |
|
||
| 微信扫码登录 | `WECHAT_APP_ID` + `WECHAT_APP_SECRET` | stub 二维码在生产被关,等于登录方式不可用 |
|
||
| 商店真实收款 | `STORE_PROVIDER=wechat` + `WXPAY_*` 全套 | 生产下 stub 返回 `payment-unavailable`(不再白嫖)|
|
||
| 媒体持久存储 | `OSS_*` 四要素(region 带 `oss-` 前缀)| 回落本地磁盘,重部署会丢片 |
|
||
| 分享卡富预览 | `SPA_INDEX_PATH`(+ Nginx 回源)| 回落 meta+跳转壳 |
|
||
| 公众号转发卡 | `WX_MP_APP_ID/SECRET`(+ JS 安全域名)| 前端休眠 no-op |
|
||
| 钱包/付费咨询栈 | `FEATURE_MARKETPLACE=true` | 默认关闭(定位「不做平台」)|
|
||
|
||
> ※ 短信/邮箱登录:这是本次安全修复的**有意行为** —— 生产没配真实 provider 就不可用,总比"回传验证码给任何人"强。要启用就配真 provider;不打算用就保证注册/登录还有邮箱密码这条路。
|
||
|
||
## ⚪ 4. 可留默认
|
||
|
||
`PORT` `EDITION=both` `JWT_EXPIRES=7d` `LLM_MODEL` `EMBED_MODEL` `AVATAR_STYLE` `TOKENS_PER_YUAN` 等。
|
||
|
||
---
|
||
|
||
## ✅ 部署后自检(3 条)
|
||
|
||
```bash
|
||
# 1) 确认进程真在 production 模式
|
||
# 启动日志应含: on :3701 (production)
|
||
|
||
# 2) 生产必须 fail-closed:忘记密码不返回验证码(响应里不应出现 devCode)
|
||
curl -s -X POST https://<api域名>/api/auth/password/forgot \
|
||
-H 'content-type: application/json' -d '{"email":"someone@x.com"}'
|
||
# 期望:{"sent":true}(无 devCode)或 502;绝不能出现 devCode 字段
|
||
|
||
# 3) 微信 mock-scan 后门必须已关(应 404)
|
||
curl -s -o /dev/null -w "%{http_code}\n" https://<api域名>/api/auth/wechat/mock-scan/anystate
|
||
# 期望:404
|
||
```
|
||
|
||
---
|
||
|
||
## ⚠️ 一次性 / 数据层
|
||
- 新增集合 `plaza_ratings` + 唯一索引 `{slug,voter}`:首次启动 `connectDb()` **自动建**,无需手动迁移。
|
||
- 未改任何既有字段(`isPublic` 等原样),无数据迁移风险。
|