fix: 移除 defaultToken 字段,彻底移除硬编码的默认密码,采用全随机密码

This commit is contained in:
时瑾 2025-09-12 18:50:21 +08:00
parent a05150ebe1
commit 8be7f74e9f
No known key found for this signature in database
GPG Key ID: 023F70A1B8F8C196
7 changed files with 28 additions and 27 deletions

View File

@ -4,14 +4,14 @@
import express from 'express';
import { createServer } from 'http';
import { randomUUID, randomBytes } from 'node:crypto'
import { randomUUID } from 'node:crypto'
import { createServer as createHttpsServer } from 'https';
import { LogWrapper } from '@/common/log';
import { NapCatPathWrapper } from '@/common/path';
import { WebUiConfigWrapper } from '@webapi/helper/config';
import { ALLRouter } from '@webapi/router';
import { cors } from '@webapi/middleware/cors';
import { createUrl } from '@webapi/utils/url';
import { createUrl, getRandomToken } from '@webapi/utils/url';
import { sendError } from '@webapi/utils/response';
import { join } from 'node:path';
import { terminalManager } from '@webapi/terminal/terminal_manager';
@ -90,9 +90,9 @@ export async function InitWebUi(logger: LogWrapper, pathWrapper: NapCatPathWrapp
let config = await WebUiConfig.GetWebUIConfig();
// 检查并更新默认密码 - 最高优先级
if (config.defaultToken || config.token === 'napcat' || !config.token) {
const randomToken = randomBytes(6).toString('hex');
await WebUiConfig.UpdateWebUIConfig({ token: randomToken, defaultToken: false });
if (config.token === 'napcat' || !config.token) {
const randomToken = getRandomToken(8);
await WebUiConfig.UpdateWebUIConfig({ token: randomToken });
logger.log(`[NapCat] [WebUi] 🔐 检测到默认密码,已自动更新为安全密码`);
// 存储token到全局变量等待QQ登录成功后发送

View File

@ -141,7 +141,7 @@ export const UpdateTokenHandler: RequestHandler = async (req, res) => {
return sendError(res, '旧 token 不匹配');
}
// 直接更新配置文件中的token不需要通过WebUiConfig.UpdateToken方法
await WebUiConfig.UpdateWebUIConfig({ token: newToken, defaultToken: false });
await WebUiConfig.UpdateWebUIConfig({ token: newToken });
// 更新内存中的缓存token使新密码立即生效
setInitialWebUiToken(newToken);

View File

@ -156,10 +156,6 @@ const checkSameTypeExists = async (pathToCheck: string, isDirectory: boolean): P
// 获取目录内容
export const ListFilesHandler: RequestHandler = async (req, res) => {
const webuiToken = await WebUiConfig.GetWebUIConfig();
if (webuiToken.defaultToken) {
return sendError(res, '默认密码禁止使用');
}
try {
const requestPath = getQueryStringParam(req.query['path']) || (isWindows ? process.env['USERPROFILE'] || 'C:\\' : '/');

View File

@ -55,9 +55,6 @@ export const CreateTerminalHandler: RequestHandler = async (req, res) => {
if (isMacOS) {
return sendError(res, 'MacOS不支持终端');
}
if ((await WebUiConfig.GetWebUIConfig()).defaultToken) {
return sendError(res, '该密码禁止创建终端');
}
try {
const { cols, rows } = req.body;
const { id } = terminalManager.createTerminal(cols, rows);

View File

@ -2,7 +2,7 @@ import { RequestHandler } from 'express';
import { existsSync, readFileSync } from 'node:fs';
import { resolve } from 'node:path';
import { loadConfig, OneBotConfig } from '@/onebot/config/config';
import { WebUiConfig, webUiPathWrapper } from '@/webui';
import { webUiPathWrapper } from '@/webui';
import { WebUiDataRuntime } from '@webapi/helper/Data';
import { sendError, sendSuccess } from '@webapi/utils/response';
import { isEmpty } from '@webapi/utils/check';
@ -47,10 +47,6 @@ export const OB11SetConfigHandler: RequestHandler = async (req, res) => {
if (isEmpty(req.body.config)) {
return sendError(res, 'config is empty');
}
const webuiToken = await WebUiConfig.GetWebUIConfig();
if (webuiToken.defaultToken) {
return sendError(res, '默认密码禁止写入配置');
}
// 写入配置
try {
// 解析并加载配置

View File

@ -7,17 +7,17 @@ import { resolve } from 'node:path';
import { deepMerge } from '../utils/object';
import { themeType } from '../types/theme';
import { getRandomToken } from '../utils/url'
// 限制尝试端口的次数,避免死循环
// 定义配置的类型
const WebUiConfigSchema = Type.Object({
host: Type.String({ default: '0.0.0.0' }),
host: Type.String({ default: '127.0.0.1' }),
port: Type.Number({ default: 6099 }),
token: Type.String({ default: 'napcat' }),
token: Type.String({ default: getRandomToken(8) }),
loginRate: Type.Number({ default: 10 }),
autoLoginAccount: Type.String({ default: '' }),
theme: themeType,
defaultToken: Type.Boolean({ default: true }),
// 是否关闭WebUI
disableWebUI: Type.Boolean({ default: false }),
// 是否关闭非局域网访问
@ -75,16 +75,17 @@ export class WebUiConfigWrapper {
this.WebUiConfigData = {
...parsedConfig,
// 首次读取内存中是没有token的需要进行一层兜底
token: getInitialWebUiToken() || parsedConfig.token
token: getInitialWebUiToken() || parsedConfig.token,
};
return this.WebUiConfigData;
} catch (e) {
console.log('读取配置文件失败', e);
const defaultConfig = this.validateAndApplyDefaults({});
return {
this.WebUiConfigData = {
...defaultConfig,
token: defaultConfig.token
};
token: getInitialWebUiToken() || defaultConfig.token,
}
return this.WebUiConfigData;
}
}
@ -126,7 +127,7 @@ export class WebUiConfigWrapper {
if (tokenToCheck !== oldToken) {
throw new Error('旧 token 不匹配');
}
await this.UpdateWebUIConfig({ token: newToken, defaultToken: false });
await this.UpdateWebUIConfig({ token: newToken });
}
// 获取日志文件夹路径

View File

@ -3,6 +3,7 @@
*/
import { isIP } from 'node:net';
import { randomBytes } from 'node:crypto'
/**
* host
@ -44,3 +45,13 @@ export const createUrl = (
}
return url.toString();
};
/**
* Token
* @param length Token长度 8
* @returns Token字符串
* @example getRandomToken
*/
export const getRandomToken = (length = 8) => {
return randomBytes(36).toString('hex').slice(0, length);
}