diff --git a/IMPROVEMENTS.md b/IMPROVEMENTS.md index de6a480..d097b76 100644 --- a/IMPROVEMENTS.md +++ b/IMPROVEMENTS.md @@ -304,27 +304,231 @@ - 影响:开发效率 - 工作量:中等 -## 九、检查清单 +## 十、缺少环境区分机制 + +### 问题描述 + +当前后端项目未区分生产环境和开发/测试环境,所有配置混在一个 `.env` 文件中。 + +**现状分析**: + +| 配置项 | 当前做法 | 问题 | +|--------|----------|------| +| DATABASE_URL | 硬编码生产数据库地址 | 开发/测试时无法切换到本地或测试数据库 | +| JWT_SECRET | 混在 .env 中 | 开发环境使用弱密钥存在安全隐患 | +| RUST_LOG | 统一设置为 `info` | 开发时需要 `debug` 级别日志 | +| APP_VERSION | 在 .env 和 Cargo.toml 两处定义 | 版本不一致 | + +**.env 当前内容**: +```bash +DATABASE_URL=postgres://milkydata:***@154.37.213.24:5432/milkydata +WECHAT_APPID="wx5b00eb90621802f7" +WECHAT_SECRET="494efc...9bfd" +JWT_SECRET="your_s..._key" +SSL_KEY_PATH=/etc/ssl/private/private.key +SSL_CERT_PATH=/etc/ssl/certs/full_chain.pem +RUST_LOG=info +APP_VERSION="0.2.0" +FREE_USER_DATA_LIMIT=20 +``` + +### 影响 + +- 开发时连接生产数据库,有误操作风险 +- 测试时无法使用独立的测试数据 +- 切换环境需要手动修改配置,容易出错 +- 生产配置泄露到代码仓库(.env 通常被 gitignore,但部署时容易混淆) + +### 解决方案 + +#### 方案一:使用 config crate(推荐) + +**添加依赖**: +```toml +# Cargo.toml +[dependencies] +config = "0.14" +serde = { version = "1.0", features = ["derive"] } +``` + +**目录结构**: +``` +rust-backend/ +├── config/ +│ ├── default.toml # 默认配置(开发) +│ ├── development.toml +│ └── production.toml +├── .env # 本地敏感配置(加入 .gitignore) +└── .env.example # 配置模板(提交到仓库) +``` + +**default.toml(开发/测试默认)**: +```toml +database_url = "postgres://milkydata:password@localhost:5432/milkydata_dev" +wechat_appid = "wx_test_appid" +wechat_secret = "test_secret" +jwt_secret = "dev-only-secret-change-in-production" +ssl_key_path = "" +ssl_cert_path = "" +rust_log = "debug" +app_version = "0.2.3" +environment = "development" +free_user_data_limit = 100 +server_host = "0.0.0.0" +server_port = 8080 +``` + +**production.toml(生产环境)**: +```toml +database_url = "postgres://milkydata:***@154.37.213.24:5432/milkydata" +wechat_appid = "wx5b00eb90621802f7" +wechat_secret = "***" +jwt_secret = "***" +ssl_key_path = "/etc/ssl/private/private.key" +ssl_cert_path = "/etc/ssl/certs/full_chain.pem" +rust_log = "info" +app_version = "0.2.3" +environment = "production" +free_user_data_limit = 20 +server_host = "0.0.0.0" +server_port = 8080 +``` + +**配置加载逻辑**: + +```rust +// src/config.rs +use config::{Config, ConfigError, File}; +use serde::Deserialize; + +#[derive(Debug, Deserialize, Clone)] +pub struct AppConfig { + pub database_url: String, + pub wechat_appid: String, + pub wechat_secret: String, + pub jwt_secret: String, + pub ssl_key_path: String, + pub ssl_cert_path: String, + pub rust_log: String, + pub app_version: String, + pub environment: String, + pub free_user_data_limit: i32, + pub server_host: String, + pub server_port: u16, +} + +impl AppConfig { + pub fn load() -> Result { + // 从环境变量读取当前环境,默认为 development + let env = std::env::var("APP_ENV").unwrap_or_else(|_| "development".into()); + + let config = Config::builder() + // 1. 先加载默认配置 + .add_source(File::with_name("config/default")) + // 2. 再加载当前环境配置(覆盖默认值) + .add_source(File::with_name(&format!("config/{}", env)).required(false)) + // 3. 最后从环境变量加载(最高优先级) + .add_source(config::Environment::with_prefix("APP")) + .build()?; + + config.try_deserialize() + } +} +``` + +#### 方案二:简化方案(最小改动) + +保持现有 `.env` 结构不变,通过 `APP_ENV` 环境变量和 `.env.development` / `.env.production` 文件区分: + +**`.env.example`(提交到仓库的配置模板)**: +```bash +# 必填配置 +DATABASE_URL=postgres://user:pass@host:port/dbname +JWT_SECRET=your-secret-key +WECHAT_APPID=your-wechat-appid +WECHAT_SECRET=your-wechat-secret + +# 可选配置(带默认值) +APP_ENV=development +RUST_LOG=info +APP_VERSION=0.2.3 +FREE_USER_DATA_LIMIT=20 +SSL_KEY_PATH= +SSL_CERT_PATH= +``` + +**部署脚本增强**: + +```bash +#!/bin/bash +# deploy.sh + +# 接收环境参数 +ENV=${1:-production} + +# 根据环境加载不同配置 +if [ "$ENV" = "development" ]; then + source .env.development +elif [ "$ENV" = "production" ]; then + source .env.production +fi + +# 构建和部署... +``` + +### 环境切换操作指南 + +| 场景 | 操作方法 | +|------|----------| +| 本地开发 | `APP_ENV=development cargo run`,连接本地数据库 | +| 测试服务器部署 | `APP_ENV=development ./deploy.sh` | +| 生产环境部署 | `APP_ENV=production ./deploy.sh` 或默认 `./deploy.sh` | +| 查看当前环境 | 启动后访问 `/health` 接口或检查日志 | + +### 实施步骤 + +**第一阶段(最小改动)**: +1. 创建 `.env.example` 配置模板,移除敏感信息 +2. 在 `deploy.sh` 中添加 `APP_ENV` 参数支持 +3. 创建 `.env.development` 本地开发配置(可选加入 .gitignore) + +**第二阶段(推荐)**: +1. 添加 `config` crate 依赖 +2. 创建 `config/default.toml` 和 `config/production.toml` +3. 重构 `config.rs` 使用 config crate +4. 更新 `deploy.sh` 使用新的配置加载方式 + +### 相关改进项 + +- 本改进与"前后端版本统一管理"(改进路线图 P1)可合并实施 +- 本改进与"拆分 main.rs 路由处理器"(改进路线图 P1)有协同效应 + +--- + +## 十一、检查清单 ### 代码提交前检查 - [ ] 通过 `cargo clippy` 检查 - [ ] 通过 `cargo fmt` 格式化 - [ ] 单元测试通过 - [ ] 无硬编码的敏感信息 +- [ ] 配置文件不包含实际密钥 ### 部署前检查 - [ ] 数据库迁移脚本准备 - [ ] 环境变量配置检查 - [ ] 备份当前版本 - [ ] 健康检查接口正常 +- [ ] 确认目标环境的配置正确 ### 安全检查 - [ ] 输入验证完整 - [ ] 错误信息不暴露敏感数据 - [ ] 认证和授权正确 - [ ] 日志不记录敏感信息 +- [ ] 生产环境使用强密钥 --- -**最后更新**:2026-04-13 -**维护者**:开发团队 \ No newline at end of file +**最后更新**:2026-04-14 +**维护者**:milky