跳到主要内容

配置中心与密钥管理

问题

如何管理服务端的配置和密钥?不同环境的配置怎么隔离?

答案

配置管理层级

基础:环境变量

config.ts
import { z } from 'zod';

// 使用 Zod 校验环境变量
const envSchema = z.object({
NODE_ENV: z.enum(['development', 'production', 'test']),
PORT: z.coerce.number().default(3000),
DATABASE_URL: z.string().url(),
REDIS_URL: z.string().url(),
JWT_SECRET: z.string().min(32),
SMTP_HOST: z.string().optional(),
});

// 启动时校验,缺少必要配置立即报错
export const env = envSchema.parse(process.env);

多环境配置

config-by-env.ts
interface AppConfig {
db: { host: string; port: number; database: string };
cache: { ttl: number };
log: { level: string };
}

const configs: Record<string, AppConfig> = {
development: {
db: { host: 'localhost', port: 5432, database: 'app_dev' },
cache: { ttl: 60 },
log: { level: 'debug' },
},
production: {
db: { host: env.DB_HOST, port: 5432, database: 'app_prod' },
cache: { ttl: 3600 },
log: { level: 'warn' },
},
};

export const config = configs[env.NODE_ENV] ?? configs.development;

密钥管理最佳实践

级别方案适用场景
基础.env + .gitignore个人开发
中级CI/CD 加密变量小团队
高级AWS Secrets Manager / Vault企业级
安全红线
  1. 永远不将 Secret 提交到 Git
  2. 不在日志中打印密钥
  3. 不在前端代码中使用服务端密钥
  4. 定期轮转密钥
secrets-manager.ts
// AWS Secrets Manager 示例
import { SecretsManager } from '@aws-sdk/client-secrets-manager';

const client = new SecretsManager({ region: 'ap-southeast-1' });

async function getSecret(name: string): Promise<string> {
const response = await client.getSecretValue({ SecretId: name });
return response.SecretString!;
}

// 启动时加载密钥
const dbPassword = await getSecret('prod/db-password');

常见面试问题

Q1: .env 文件和环境变量的优先级?

答案

一般约定:系统环境变量 > .env.local > .env.[mode] > .envdotenv 默认不覆盖已有环境变量,所以系统环境变量优先级最高。

Q2: 配置热更新怎么实现?

答案

  1. 配置中心:应用定时轮询或通过长连接监听变更
  2. Feature Flags:LaunchDarkly、ConfigCat 等 SaaS 服务
  3. K8s ConfigMap:挂载为文件,通过 fs.watch 监听变化

Q3: 前端和后端的环境变量有什么区别?

答案

  • 前端:构建时注入,打包后不可变,公开暴露(NEXT_PUBLIC_VITE_ 前缀)
  • 后端:运行时读取,可动态修改,不暴露给客户端

相关链接