fix: 加固聊天限流与安全策略串行化

This commit is contained in:
root
2026-09-16 14:20:23 +08:00
parent 8a12c04104
commit 02189ebb2e
10 changed files with 299 additions and 43 deletions
@@ -5,7 +5,6 @@ import { RedisService } from "../redis/redis.service.js";
export class ChatRateLimiter {
constructor(@Inject(RedisService) private readonly redis: RedisService) {}
async consume(accountId: string, sessionId: string): Promise<boolean> {
await this.redis.ensureConnected();
const prefix = process.env.REDIS_KEY_PREFIX ?? "drift:auth:";
const max = Number(process.env.CHAT_MESSAGE_RATE_LIMIT ?? 30);
const ttl = Number(process.env.CHAT_MESSAGE_RATE_WINDOW_SECONDS ?? 60);
@@ -13,9 +12,11 @@ export class ChatRateLimiter {
`${prefix}chat:account:${accountId}`,
`${prefix}chat:session:${sessionId}`,
];
const result = await this.redis.client.eval(
`for _,k in ipairs(KEYS) do if tonumber(redis.call('GET',k) or '0')+1>tonumber(ARGV[1]) then return 0 end end; for _,k in ipairs(KEYS) do local n=redis.call('INCR',k); if n==1 then redis.call('EXPIRE',k,ARGV[2]) end end; return 1`,
{ keys, arguments: [String(max), String(ttl)] },
const result = await this.redis.executeWithDeadline((client) =>
client.eval(
`for _,k in ipairs(KEYS) do if tonumber(redis.call('GET',k) or '0')+1>tonumber(ARGV[1]) then return 0 end end; for _,k in ipairs(KEYS) do local n=redis.call('INCR',k); if n==1 then redis.call('EXPIRE',k,ARGV[2]) end end; return 1`,
{ keys, arguments: [String(max), String(ttl)] },
),
);
return Number(result) === 1;
}