diff --git a/.gitignore b/.gitignore index 8bf35c1..3608da2 100644 --- a/.gitignore +++ b/.gitignore @@ -27,6 +27,11 @@ run/ # 含本地 DB 口令,故排除入库;如需团队共享请提交不含口令的 config.local.example.js config/config.local.js +# sequelize-cli 数据库配置(含本地 DB 口令)—— 2026-09-23 入库口令处置 P1 +# 仓库内保留不含口令的 database/config.json.example;使用前复制并填入口令: +# cp database/config.json.example database/config.json +database/config.json + # Coverage / cache coverage/ .cache/ diff --git a/add_word_cols.js b/add_word_cols.js index da72823..ee66d9b 100644 --- a/add_word_cols.js +++ b/add_word_cols.js @@ -1,7 +1,12 @@ const mysql = require('mysql2/promise'); (async () => { + // 🔴 口令不再内置明文(2026-09-23 入库口令处置 P2)。运行前请注入 DB_PASSWORD: + // DB_PASSWORD='<本机 DB 口令>' node add_word_cols.js const c = await mysql.createConnection({ - host: 'localhost', user: 'root', password: '74191221', database: 'competition_db' + host: process.env.DB_HOST || 'localhost', + user: process.env.DB_USER || 'root', + password: process.env.DB_PASSWORD, + database: process.env.DB_NAME || 'competition_db', }); try { await c.query("ALTER TABLE exam_submissions ADD COLUMN word_file_path VARCHAR(500) NULL DEFAULT NULL COMMENT 'Word答案文件路径' AFTER answers"); diff --git a/add_wx_link.js b/add_wx_link.js index 62bb7d5..ed8346d 100644 --- a/add_wx_link.js +++ b/add_wx_link.js @@ -1,7 +1,12 @@ const mysql = require('mysql2/promise'); (async () => { + // 🔴 口令不再内置明文(2026-09-23 入库口令处置 P2)。运行前请注入 DB_PASSWORD: + // DB_PASSWORD='<本机 DB 口令>' node add_wx_link.js const c = await mysql.createConnection({ - host: 'localhost', user: 'root', password: '74191221', database: 'competition_db' + host: process.env.DB_HOST || 'localhost', + user: process.env.DB_USER || 'root', + password: process.env.DB_PASSWORD, + database: process.env.DB_NAME || 'competition_db', }); try { await c.query("ALTER TABLE news ADD COLUMN wx_link VARCHAR(500) NULL DEFAULT NULL COMMENT '微信公众号文章链接' AFTER content"); diff --git a/config/config.default.js b/config/config.default.js index 2af3a2d..f16610d 100644 --- a/config/config.default.js +++ b/config/config.default.js @@ -217,8 +217,10 @@ module.exports = (appInfo) => { port: parseInt(process.env.DB_PORT, 10) || 3306, // 兼容 docker-compose/.env.example 中的 DB_USER 与代码历史使用的 DB_USERNAME username: process.env.DB_USERNAME || process.env.DB_USER || 'root', - // 【测试模拟值 '74191221',仅供本地/测试部署;生产请通过 DB_PASSWORD 环境变量注入真实密码】 - password: process.env.DB_PASSWORD || '74191221', + // 🔴 口令不再内置明文兜底(2026-09-23 入库口令处置 P3): + // 生产 —— 必须由 .env.production 注入 DB_PASSWORD(缺失则由下方生产安全守卫阻断启动); + // 本地 —— 由 config/config.local.js(已 gitignore)深合并覆盖为真实本机口令。 + password: process.env.DB_PASSWORD, timezone: '+08:00', define: { underscored: true, @@ -279,7 +281,8 @@ module.exports = (appInfo) => { client: { port: parseInt(process.env.REDIS_PORT, 10) || 6379, host: process.env.REDIS_HOST || '127.0.0.1', - password: process.env.REDIS_PASSWORD || '74191221', + // 🔴 同上:不再内置明文兜底(2026-09-23 P3)。Redis 当前全库无使用点,留空为零影响。 + password: process.env.REDIS_PASSWORD || '', db: 0, }, }; @@ -442,6 +445,11 @@ module.exports = (appInfo) => { const insecure = []; if (config.jwt.secret === DEFAULT_JWT_SECRET) insecure.push('JWT_SECRET'); if (config.keys === DEFAULT_APP_KEYS) insecure.push('APP_KEYS'); + // 🔴 2026-09-23(入库口令处置 P3):口令缺失同样阻断。 + // 原实现在此处会静默回退到公开的开发口令,等价于「生产用公开口令连库」。 + // 现要求生产必须显式注入 DB_PASSWORD(deploy/.env.production 本就含该键, + // 故现网永不触发本分支;一旦触发说明注入链路断了,明确阻断优于连不上库)。 + if (!config.sequelize.password) insecure.push('DB_PASSWORD'); if (insecure.length > 0) { // 生产环境仍在使用硬编码默认密钥属于严重安全隐患,直接阻断启动 throw new Error( diff --git a/database/config.json b/database/config.json.example similarity index 94% rename from database/config.json rename to database/config.json.example index f895899..d8150ce 100644 --- a/database/config.json +++ b/database/config.json.example @@ -1,7 +1,7 @@ -{ +{ "development": { "username": "root", - "password": "74191221", + "password": "CHANGE_ME_local_db_password", "database": "competition_db", "host": "localhost", "port": 3306, @@ -24,7 +24,7 @@ }, "test": { "username": "root", - "password": "74191221", + "password": "CHANGE_ME_local_db_password", "database": "competition_db_test", "host": "localhost", "port": 3306, diff --git a/scripts/diagnose_upload_download.cjs b/scripts/diagnose_upload_download.cjs index 98a684b..d6adcea 100644 --- a/scripts/diagnose_upload_download.cjs +++ b/scripts/diagnose_upload_download.cjs @@ -12,7 +12,7 @@ * cd <生产 backend 目录> * node scripts/diagnose_upload_download.cjs * # 如需抽查数据库(可选): - * DB_HOST=127.0.0.1 DB_USER=root DB_PASS=74191221 DB_NAME=competition_db \ + * DB_HOST=127.0.0.1 DB_USER=root DB_PASS='<本机 DB 口令>' DB_NAME=competition_db \ * node scripts/diagnose_upload_download.cjs * * 不依赖 Egg 启动,纯 Node + fs 即可;DB 部分为可选(拿不到模块/连接失败则跳过)。 @@ -114,7 +114,7 @@ console.log('--- 4. 数据库 submission.file_path 真实性抽查(可选)-- const dbCfg = { host: process.env.DB_HOST || '127.0.0.1', user: process.env.DB_USER || 'root', - password: process.env.DB_PASS || '74191221', + password: process.env.DB_PASS, database: process.env.DB_NAME || 'competition_db', }; diff --git a/seed-carousel.js b/seed-carousel.js index 8c3467e..5e7b97c 100644 --- a/seed-carousel.js +++ b/seed-carousel.js @@ -1,8 +1,17 @@ const { Sequelize } = require('./node_modules/sequelize'); -const sequelize = new Sequelize('competition_db', 'root', '74191221', { - host: 'localhost', port: 3306, dialect: 'mysql', - logging: false -}); +// 🔴 口令不再内置明文(2026-09-23 入库口令处置 P2)。运行前请注入 DB_PASSWORD: +// DB_PASSWORD='<本机 DB 口令>' node seed-carousel.js +const sequelize = new Sequelize( + process.env.DB_NAME || 'competition_db', + process.env.DB_USER || 'root', + process.env.DB_PASSWORD, + { + host: process.env.DB_HOST || 'localhost', + port: parseInt(process.env.DB_PORT, 10) || 3306, + dialect: 'mysql', + logging: false, + } +); (async () => { try { diff --git a/show_tables.js b/show_tables.js index 4df1a98..46f5f68 100644 --- a/show_tables.js +++ b/show_tables.js @@ -1,7 +1,12 @@ const mysql = require('mysql2/promise'); (async () => { + // 🔴 口令不再内置明文(2026-09-23 入库口令处置 P2)。运行前请注入 DB_PASSWORD: + // DB_PASSWORD='<本机 DB 口令>' node show_tables.js const c = await mysql.createConnection({ - host: 'localhost', user: 'root', password: '74191221', database: 'competition_db' + host: process.env.DB_HOST || 'localhost', + user: process.env.DB_USER || 'root', + password: process.env.DB_PASSWORD, + database: process.env.DB_NAME || 'competition_db', }); const [t] = await c.query('SHOW TABLES'); t.forEach(r => console.log(Object.values(r)[0]));