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:
40
server.js
40
server.js
@@ -1,5 +1,5 @@
|
||||
import express from 'express';
|
||||
import { loadConfig, isDevMode, getPort } from './config.js';
|
||||
import { loadConfig, isDevMode, getPort, getCorsConfig } from './config.js';
|
||||
import { logInfo, logError } from './logger.js';
|
||||
import router from './routes.js';
|
||||
import { initializeAuth } from './auth.js';
|
||||
@@ -108,13 +108,41 @@ const app = express();
|
||||
app.use(express.json({ limit: '50mb' }));
|
||||
app.use(express.urlencoded({ extended: true, limit: '50mb' }));
|
||||
|
||||
/**
|
||||
* CORS 中间件 - 根据配置动态处理跨域请求
|
||||
*/
|
||||
app.use((req, res, next) => {
|
||||
res.header('Access-Control-Allow-Origin', '*');
|
||||
res.header('Access-Control-Allow-Methods', 'GET, POST, PUT, DELETE, OPTIONS');
|
||||
res.header('Access-Control-Allow-Headers', 'Content-Type, Authorization, X-API-Key, anthropic-version');
|
||||
|
||||
const corsConfig = getCorsConfig();
|
||||
|
||||
// 如果 CORS 完全禁用,直接跳过
|
||||
if (!corsConfig.enabled) {
|
||||
if (req.method === 'OPTIONS') {
|
||||
return res.sendStatus(204);
|
||||
}
|
||||
return next();
|
||||
}
|
||||
|
||||
const origin = req.headers.origin;
|
||||
|
||||
// 设置允许的方法和头
|
||||
res.header('Access-Control-Allow-Methods', corsConfig.methods.join(', '));
|
||||
res.header('Access-Control-Allow-Headers', corsConfig.headers.join(', '));
|
||||
|
||||
if (corsConfig.allowAll) {
|
||||
// 允许所有来源(仅用于开发环境)
|
||||
res.header('Access-Control-Allow-Origin', '*');
|
||||
} else if (origin && corsConfig.origins.length > 0) {
|
||||
// 白名单模式:验证请求来源
|
||||
if (corsConfig.origins.includes(origin)) {
|
||||
res.header('Access-Control-Allow-Origin', origin);
|
||||
res.header('Vary', 'Origin');
|
||||
}
|
||||
// 不在白名单中的请求不设置 CORS 头,浏览器会拒绝
|
||||
}
|
||||
// 如果没有配置 origins 且不是 allowAll,则不设置任何 CORS 头
|
||||
|
||||
if (req.method === 'OPTIONS') {
|
||||
return res.sendStatus(200);
|
||||
return res.sendStatus(204);
|
||||
}
|
||||
next();
|
||||
});
|
||||
|
||||
Reference in New Issue
Block a user