mirror of
https://github.com/NapNeko/NapCatQQ.git
synced 2025-12-20 05:30:06 +08:00
fix: 移除 defaultToken 字段,彻底移除硬编码的默认密码,采用全随机密码
This commit is contained in:
parent
a05150ebe1
commit
8be7f74e9f
@ -4,14 +4,14 @@
|
|||||||
|
|
||||||
import express from 'express';
|
import express from 'express';
|
||||||
import { createServer } from 'http';
|
import { createServer } from 'http';
|
||||||
import { randomUUID, randomBytes } from 'node:crypto'
|
import { randomUUID } from 'node:crypto'
|
||||||
import { createServer as createHttpsServer } from 'https';
|
import { createServer as createHttpsServer } from 'https';
|
||||||
import { LogWrapper } from '@/common/log';
|
import { LogWrapper } from '@/common/log';
|
||||||
import { NapCatPathWrapper } from '@/common/path';
|
import { NapCatPathWrapper } from '@/common/path';
|
||||||
import { WebUiConfigWrapper } from '@webapi/helper/config';
|
import { WebUiConfigWrapper } from '@webapi/helper/config';
|
||||||
import { ALLRouter } from '@webapi/router';
|
import { ALLRouter } from '@webapi/router';
|
||||||
import { cors } from '@webapi/middleware/cors';
|
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 { sendError } from '@webapi/utils/response';
|
||||||
import { join } from 'node:path';
|
import { join } from 'node:path';
|
||||||
import { terminalManager } from '@webapi/terminal/terminal_manager';
|
import { terminalManager } from '@webapi/terminal/terminal_manager';
|
||||||
@ -90,9 +90,9 @@ export async function InitWebUi(logger: LogWrapper, pathWrapper: NapCatPathWrapp
|
|||||||
let config = await WebUiConfig.GetWebUIConfig();
|
let config = await WebUiConfig.GetWebUIConfig();
|
||||||
|
|
||||||
// 检查并更新默认密码 - 最高优先级
|
// 检查并更新默认密码 - 最高优先级
|
||||||
if (config.defaultToken || config.token === 'napcat' || !config.token) {
|
if (config.token === 'napcat' || !config.token) {
|
||||||
const randomToken = randomBytes(6).toString('hex');
|
const randomToken = getRandomToken(8);
|
||||||
await WebUiConfig.UpdateWebUIConfig({ token: randomToken, defaultToken: false });
|
await WebUiConfig.UpdateWebUIConfig({ token: randomToken });
|
||||||
logger.log(`[NapCat] [WebUi] 🔐 检测到默认密码,已自动更新为安全密码`);
|
logger.log(`[NapCat] [WebUi] 🔐 检测到默认密码,已自动更新为安全密码`);
|
||||||
|
|
||||||
// 存储token到全局变量,等待QQ登录成功后发送
|
// 存储token到全局变量,等待QQ登录成功后发送
|
||||||
|
|||||||
@ -141,7 +141,7 @@ export const UpdateTokenHandler: RequestHandler = async (req, res) => {
|
|||||||
return sendError(res, '旧 token 不匹配');
|
return sendError(res, '旧 token 不匹配');
|
||||||
}
|
}
|
||||||
// 直接更新配置文件中的token,不需要通过WebUiConfig.UpdateToken方法
|
// 直接更新配置文件中的token,不需要通过WebUiConfig.UpdateToken方法
|
||||||
await WebUiConfig.UpdateWebUIConfig({ token: newToken, defaultToken: false });
|
await WebUiConfig.UpdateWebUIConfig({ token: newToken });
|
||||||
// 更新内存中的缓存token,使新密码立即生效
|
// 更新内存中的缓存token,使新密码立即生效
|
||||||
setInitialWebUiToken(newToken);
|
setInitialWebUiToken(newToken);
|
||||||
|
|
||||||
|
|||||||
@ -156,10 +156,6 @@ const checkSameTypeExists = async (pathToCheck: string, isDirectory: boolean): P
|
|||||||
|
|
||||||
// 获取目录内容
|
// 获取目录内容
|
||||||
export const ListFilesHandler: RequestHandler = async (req, res) => {
|
export const ListFilesHandler: RequestHandler = async (req, res) => {
|
||||||
const webuiToken = await WebUiConfig.GetWebUIConfig();
|
|
||||||
if (webuiToken.defaultToken) {
|
|
||||||
return sendError(res, '默认密码禁止使用');
|
|
||||||
}
|
|
||||||
try {
|
try {
|
||||||
const requestPath = getQueryStringParam(req.query['path']) || (isWindows ? process.env['USERPROFILE'] || 'C:\\' : '/');
|
const requestPath = getQueryStringParam(req.query['path']) || (isWindows ? process.env['USERPROFILE'] || 'C:\\' : '/');
|
||||||
|
|
||||||
|
|||||||
@ -55,9 +55,6 @@ export const CreateTerminalHandler: RequestHandler = async (req, res) => {
|
|||||||
if (isMacOS) {
|
if (isMacOS) {
|
||||||
return sendError(res, 'MacOS不支持终端');
|
return sendError(res, 'MacOS不支持终端');
|
||||||
}
|
}
|
||||||
if ((await WebUiConfig.GetWebUIConfig()).defaultToken) {
|
|
||||||
return sendError(res, '该密码禁止创建终端');
|
|
||||||
}
|
|
||||||
try {
|
try {
|
||||||
const { cols, rows } = req.body;
|
const { cols, rows } = req.body;
|
||||||
const { id } = terminalManager.createTerminal(cols, rows);
|
const { id } = terminalManager.createTerminal(cols, rows);
|
||||||
|
|||||||
@ -2,7 +2,7 @@ import { RequestHandler } from 'express';
|
|||||||
import { existsSync, readFileSync } from 'node:fs';
|
import { existsSync, readFileSync } from 'node:fs';
|
||||||
import { resolve } from 'node:path';
|
import { resolve } from 'node:path';
|
||||||
import { loadConfig, OneBotConfig } from '@/onebot/config/config';
|
import { loadConfig, OneBotConfig } from '@/onebot/config/config';
|
||||||
import { WebUiConfig, webUiPathWrapper } from '@/webui';
|
import { webUiPathWrapper } from '@/webui';
|
||||||
import { WebUiDataRuntime } from '@webapi/helper/Data';
|
import { WebUiDataRuntime } from '@webapi/helper/Data';
|
||||||
import { sendError, sendSuccess } from '@webapi/utils/response';
|
import { sendError, sendSuccess } from '@webapi/utils/response';
|
||||||
import { isEmpty } from '@webapi/utils/check';
|
import { isEmpty } from '@webapi/utils/check';
|
||||||
@ -47,10 +47,6 @@ export const OB11SetConfigHandler: RequestHandler = async (req, res) => {
|
|||||||
if (isEmpty(req.body.config)) {
|
if (isEmpty(req.body.config)) {
|
||||||
return sendError(res, 'config is empty');
|
return sendError(res, 'config is empty');
|
||||||
}
|
}
|
||||||
const webuiToken = await WebUiConfig.GetWebUIConfig();
|
|
||||||
if (webuiToken.defaultToken) {
|
|
||||||
return sendError(res, '默认密码禁止写入配置');
|
|
||||||
}
|
|
||||||
// 写入配置
|
// 写入配置
|
||||||
try {
|
try {
|
||||||
// 解析并加载配置
|
// 解析并加载配置
|
||||||
|
|||||||
@ -7,17 +7,17 @@ import { resolve } from 'node:path';
|
|||||||
|
|
||||||
import { deepMerge } from '../utils/object';
|
import { deepMerge } from '../utils/object';
|
||||||
import { themeType } from '../types/theme';
|
import { themeType } from '../types/theme';
|
||||||
|
import { getRandomToken } from '../utils/url'
|
||||||
|
|
||||||
// 限制尝试端口的次数,避免死循环
|
// 限制尝试端口的次数,避免死循环
|
||||||
// 定义配置的类型
|
// 定义配置的类型
|
||||||
const WebUiConfigSchema = Type.Object({
|
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 }),
|
port: Type.Number({ default: 6099 }),
|
||||||
token: Type.String({ default: 'napcat' }),
|
token: Type.String({ default: getRandomToken(8) }),
|
||||||
loginRate: Type.Number({ default: 10 }),
|
loginRate: Type.Number({ default: 10 }),
|
||||||
autoLoginAccount: Type.String({ default: '' }),
|
autoLoginAccount: Type.String({ default: '' }),
|
||||||
theme: themeType,
|
theme: themeType,
|
||||||
defaultToken: Type.Boolean({ default: true }),
|
|
||||||
// 是否关闭WebUI
|
// 是否关闭WebUI
|
||||||
disableWebUI: Type.Boolean({ default: false }),
|
disableWebUI: Type.Boolean({ default: false }),
|
||||||
// 是否关闭非局域网访问
|
// 是否关闭非局域网访问
|
||||||
@ -75,16 +75,17 @@ export class WebUiConfigWrapper {
|
|||||||
this.WebUiConfigData = {
|
this.WebUiConfigData = {
|
||||||
...parsedConfig,
|
...parsedConfig,
|
||||||
// 首次读取内存中是没有token的,需要进行一层兜底
|
// 首次读取内存中是没有token的,需要进行一层兜底
|
||||||
token: getInitialWebUiToken() || parsedConfig.token
|
token: getInitialWebUiToken() || parsedConfig.token,
|
||||||
};
|
};
|
||||||
return this.WebUiConfigData;
|
return this.WebUiConfigData;
|
||||||
} catch (e) {
|
} catch (e) {
|
||||||
console.log('读取配置文件失败', e);
|
console.log('读取配置文件失败', e);
|
||||||
const defaultConfig = this.validateAndApplyDefaults({});
|
const defaultConfig = this.validateAndApplyDefaults({});
|
||||||
return {
|
this.WebUiConfigData = {
|
||||||
...defaultConfig,
|
...defaultConfig,
|
||||||
token: defaultConfig.token
|
token: getInitialWebUiToken() || defaultConfig.token,
|
||||||
};
|
}
|
||||||
|
return this.WebUiConfigData;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -126,7 +127,7 @@ export class WebUiConfigWrapper {
|
|||||||
if (tokenToCheck !== oldToken) {
|
if (tokenToCheck !== oldToken) {
|
||||||
throw new Error('旧 token 不匹配');
|
throw new Error('旧 token 不匹配');
|
||||||
}
|
}
|
||||||
await this.UpdateWebUIConfig({ token: newToken, defaultToken: false });
|
await this.UpdateWebUIConfig({ token: newToken });
|
||||||
}
|
}
|
||||||
|
|
||||||
// 获取日志文件夹路径
|
// 获取日志文件夹路径
|
||||||
|
|||||||
@ -3,6 +3,7 @@
|
|||||||
*/
|
*/
|
||||||
|
|
||||||
import { isIP } from 'node:net';
|
import { isIP } from 'node:net';
|
||||||
|
import { randomBytes } from 'node:crypto'
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 将 host(主机地址) 转换为标准格式
|
* 将 host(主机地址) 转换为标准格式
|
||||||
@ -44,3 +45,13 @@ export const createUrl = (
|
|||||||
}
|
}
|
||||||
return url.toString();
|
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);
|
||||||
|
}
|
||||||
|
|||||||
Loading…
Reference in New Issue
Block a user