feat: 实现可配置的 CORS 安全策略

- 添加 getCorsConfig() 函数支持灵活的 CORS 配置
- 支持三种模式:禁用 CORS、白名单、允许所有来源
- 环境变量可覆盖 config.json 配置 (CORS_ENABLED, CORS_ALLOW_ALL, CORS_ORIGINS)
- config.json 默认使用白名单模式,仅允许 localhost
- 动态验证 Origin 头,不在白名单的请求不设置 CORS 头
- 添加 Vary: Origin 头支持 CDN 缓存

安全改进:
- 生产环境默认 allow_all=false,避免 CORS 通配符
- 白名单模式下,未授权来源的请求会被浏览器拒绝

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
This commit is contained in:
empty
2025-12-27 15:33:04 +08:00
parent 3dccbcfed1
commit eef909c5dd
4 changed files with 90 additions and 8 deletions

View File

@@ -91,3 +91,43 @@ export function getRedirectedModelId(modelId) {
}
return modelId;
}
/**
* 获取 CORS 配置
* 优先级: 环境变量 > config.json > 默认值
* @returns {Object} CORS 配置对象
*/
export function getCorsConfig() {
const cfg = getConfig();
const configCors = cfg.cors || {};
// 环境变量覆盖
const envAllowAll = process.env.CORS_ALLOW_ALL;
const envOrigins = process.env.CORS_ORIGINS;
// 解析 allow_all
let allowAll = configCors.allow_all ?? false;
if (envAllowAll !== undefined) {
allowAll = ['true', '1', 'yes'].includes(envAllowAll.toLowerCase());
}
// 解析 origins
let origins = configCors.origins || [];
if (envOrigins) {
origins = envOrigins.split(',').map(o => o.trim()).filter(o => o);
}
// 解析 enabled
let enabled = configCors.enabled ?? true;
if (process.env.CORS_ENABLED !== undefined) {
enabled = ['true', '1', 'yes'].includes(process.env.CORS_ENABLED.toLowerCase());
}
return {
enabled,
allowAll,
origins,
methods: configCors.methods || ['GET', 'POST', 'PUT', 'DELETE', 'OPTIONS'],
headers: configCors.headers || ['Content-Type', 'Authorization', 'X-API-Key', 'anthropic-version']
};
}