mirror of
https://github.com/crystelf/crystelf-core.git
synced 2025-07-04 14:49:19 +00:00
关闭未认证的WebSocket连接并重构Redis服务
在WebSocket认证失败时,主动关闭连接以提高安全性。重构了Redis服务中的方法,使其更加通用,并更新了相关的导入和调用。同时,调整了数据持久化路径的生成方式,支持自定义文件名。
This commit is contained in:
parent
a996bed065
commit
4a82585c29
@ -2,9 +2,9 @@ import Redis from 'ioredis';
|
||||
import logger from '../../utils/core/logger';
|
||||
import tools from '../../utils/core/tool';
|
||||
import config from '../../utils/core/config';
|
||||
import redisTool from '../../utils/redis/redisTools';
|
||||
import IUser from '../../types/user';
|
||||
import redisTools from '../../utils/redis/redisTools';
|
||||
import Persistence from '../../utils/redis/persistence';
|
||||
import IUser from '../../types/user';
|
||||
|
||||
class RedisService {
|
||||
private client!: Redis;
|
||||
@ -93,7 +93,7 @@ class RedisService {
|
||||
}
|
||||
|
||||
public async setObject<T>(key: string, value: T, ttl?: number): Promise<void> {
|
||||
const serialized = redisTool.serialize(value);
|
||||
const serialized = redisTools.serialize(value);
|
||||
await this.getClient().set(key, serialized);
|
||||
|
||||
if (ttl) {
|
||||
@ -105,66 +105,40 @@ class RedisService {
|
||||
const serialized = await this.getClient().get(key);
|
||||
if (!serialized) return undefined;
|
||||
|
||||
const deserialized = redisTool.deserialize<T>(serialized);
|
||||
return redisTool.reviveDates(deserialized);
|
||||
const deseralized = redisTools.deserialize<T>(serialized);
|
||||
return redisTools.reviveDates(deseralized);
|
||||
}
|
||||
|
||||
public async updateUser(qq: string, updates: Partial<IUser>): Promise<IUser> {
|
||||
const existing = await this.getObject<IUser>(`user:${qq}`);
|
||||
public async update<T>(key: string, updates: T): Promise<T> {
|
||||
const existing = await this.getObject<T>(key);
|
||||
if (!existing) {
|
||||
throw new Error(`用户 ${qq} 不存在`);
|
||||
logger.error(`数据${key}不存在..`);
|
||||
}
|
||||
const updatedUser = { ...existing, ...updates, updatedAt: new Date() };
|
||||
await this.persistUser(updatedUser);
|
||||
return updatedUser;
|
||||
const updated = { ...existing, ...updates };
|
||||
await this.setObject(key, updated);
|
||||
return updated;
|
||||
}
|
||||
|
||||
public async persistUser<T extends IUser>(user: T): Promise<void> {
|
||||
try {
|
||||
await Promise.all([
|
||||
this.setObject(`user:${user.qq}`, user),
|
||||
Persistence.writeDataLocal(user.name, user),
|
||||
]);
|
||||
} catch (err) {
|
||||
logger.error(err);
|
||||
throw err;
|
||||
}
|
||||
}
|
||||
|
||||
public async fetchUser<T extends IUser>(
|
||||
qq: string,
|
||||
username: string
|
||||
): Promise<IUser | undefined> {
|
||||
try {
|
||||
const fromRedis = await this.getObject<IUser>(`user:${qq}`);
|
||||
if (fromRedis) return fromRedis;
|
||||
|
||||
const fromLocal = await Persistence.readDataLocal<IUser>(username);
|
||||
public async fetch<T>(key: string, fileName: string): Promise<T | undefined> {
|
||||
const data = await this.getObject<T>(key);
|
||||
if (data) return data;
|
||||
const fromLocal = await Persistence.readDataLocal<T>(key, fileName);
|
||||
if (fromLocal) {
|
||||
await this.setObject(`user:${qq}`, fromLocal);
|
||||
await this.setObject(key, fromLocal);
|
||||
return fromLocal;
|
||||
}
|
||||
|
||||
logger.error(`用户${username},qq${qq}不存在!`);
|
||||
return undefined;
|
||||
} catch (err) {
|
||||
logger.error(err);
|
||||
throw err;
|
||||
logger.error(`数据${key}不存在..`);
|
||||
}
|
||||
|
||||
public async persistData<T>(key: string, data: T, fileName: string): Promise<void> {
|
||||
await this.setObject(key, data);
|
||||
await Persistence.writeDataLocal(key, data, fileName);
|
||||
return;
|
||||
}
|
||||
|
||||
public async test(): Promise<void> {
|
||||
const testData: IUser = {
|
||||
name: 'Jerry',
|
||||
qq: '114514',
|
||||
isAdmin: true,
|
||||
password: '114514',
|
||||
createdAt: new Date(),
|
||||
};
|
||||
|
||||
await this.persistUser(testData);
|
||||
const user = await this.fetchUser('114514', 'Jerry');
|
||||
logger.debug(user);
|
||||
const user = await this.fetch<IUser>('Jerry', 'IUser');
|
||||
logger.debug('User:', user);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -83,6 +83,7 @@ class WSServer {
|
||||
} else {
|
||||
logger.warn(`Auth failed from ${ip} (invalid secret), clientId: ${msg.clientId}`);
|
||||
await WsTools.send(socket, { type: 'auth', success: false });
|
||||
socket.close(4001, 'Authentication failed');
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -5,8 +5,8 @@ import logger from '../core/logger';
|
||||
import fs from 'fs/promises';
|
||||
|
||||
class Persistence {
|
||||
private static getUserDataPath(username: string): string {
|
||||
return path.join(paths.get('userData'), username, 'data.json');
|
||||
private static getUserDataPath(username: string, fileName: string): string {
|
||||
return path.join(paths.get('userData'), username, `${fileName}.json`);
|
||||
}
|
||||
|
||||
private static async ensureUserPath(username: string): Promise<void> {
|
||||
@ -18,9 +18,13 @@ class Persistence {
|
||||
}
|
||||
}
|
||||
|
||||
public static async writeDataLocal<T>(username: string, data: T): Promise<void> {
|
||||
public static async writeDataLocal<T>(
|
||||
username: string,
|
||||
data: T,
|
||||
fileName: string
|
||||
): Promise<void> {
|
||||
await this.ensureUserPath(username);
|
||||
const filePath = this.getUserDataPath(username);
|
||||
const filePath = this.getUserDataPath(username, fileName);
|
||||
|
||||
try {
|
||||
await fs.writeFile(filePath, JSON.stringify(data, null, 2), 'utf-8');
|
||||
@ -30,8 +34,8 @@ class Persistence {
|
||||
}
|
||||
}
|
||||
|
||||
public static async readDataLocal<T>(username: string): Promise<T | undefined> {
|
||||
const filePath = this.getUserDataPath(username);
|
||||
public static async readDataLocal<T>(username: string, fileName: string): Promise<T | undefined> {
|
||||
const filePath = this.getUserDataPath(username, fileName);
|
||||
|
||||
try {
|
||||
const data = await fs.readFile(filePath, 'utf-8');
|
||||
|
Loading…
x
Reference in New Issue
Block a user