1
0
mirror of https://github.com/ZeroCatDev/ClassworksKV.git synced 2025-07-02 04:39:23 +00:00
ClassworksKV/middleware/rateLimiter.js

108 lines
3.6 KiB
JavaScript
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

import rateLimit from "express-rate-limit";
// 获取客户端真实IP的函数
export const getClientIp = (req) => {
return (
req.headers["x-forwarded-for"] ||
req.connection.remoteAddress ||
req.socket.remoteAddress ||
req.connection.socket?.remoteAddress ||
"0.0.0.0"
);
};
// 配置全局限速中间件
export const globalLimiter = rateLimit({
windowMs: 15 * 60 * 1000, // 15分钟
limit: 200, // 每个IP在windowMs时间内最多允许200个请求
standardHeaders: "draft-7", // 返回标准的RateLimit头信息
legacyHeaders: false, // 禁用X-RateLimit-*头
message: "请求过于频繁,请稍后再试",
keyGenerator: getClientIp, // 使用真实IP作为限速键
skipSuccessfulRequests: false, // 成功的请求也计入限制
skipFailedRequests: false, // 失败的请求也计入限制
});
// API限速器
export const apiLimiter = rateLimit({
windowMs: 1 * 60 * 1000, // 1分钟
limit: 50, // 每个IP在windowMs时间内最多允许50个请求
standardHeaders: "draft-7",
legacyHeaders: false,
message: "API请求过于频繁请稍后再试",
keyGenerator: getClientIp,
skipSuccessfulRequests: false,
skipFailedRequests: false,
});
// 写操作限速器(更严格)
export const writeLimiter = rateLimit({
windowMs: 1 * 60 * 1000, // 1分钟
limit: 20, // 每个IP在windowMs时间内最多允许20个写操作
standardHeaders: "draft-7",
legacyHeaders: false,
message: "写操作请求过于频繁,请稍后再试",
keyGenerator: getClientIp,
skipSuccessfulRequests: false,
skipFailedRequests: false,
});
// 删除操作限速器(最严格)
export const deleteLimiter = rateLimit({
windowMs: 1 * 60 * 1000, // 5分钟
limit: 10, // 每个IP在windowMs时间内最多允许10个删除操作
standardHeaders: "draft-7",
legacyHeaders: false,
message: "删除操作请求过于频繁,请稍后再试",
keyGenerator: getClientIp,
skipSuccessfulRequests: false,
skipFailedRequests: false,
});
// 认证相关路由限速器(防止暴力破解)
export const authLimiter = rateLimit({
windowMs: 30 * 60 * 1000, // 30分钟
limit: 5, // 每个IP在windowMs时间内最多允许5次认证尝试
standardHeaders: "draft-7",
legacyHeaders: false,
message: "认证请求过于频繁请30分钟后再试",
keyGenerator: getClientIp,
skipSuccessfulRequests: true, // 成功的认证不计入限制
skipFailedRequests: false, // 失败的认证计入限制
});
// 批量操作限速器(比写操作更严格)
export const batchLimiter = rateLimit({
windowMs: 1 * 60 * 1000, // 5分钟
limit: 10, // 每个IP在windowMs时间内最多允许10个批量操作
standardHeaders: "draft-7",
legacyHeaders: false,
message: "批量操作请求过于频繁,请稍后再试",
keyGenerator: getClientIp,
skipSuccessfulRequests: false,
skipFailedRequests: false,
});
// 创建一个路由处理中间件根据HTTP方法应用不同的限速器
export const methodBasedRateLimiter = (req, res, next) => {
// 检查是否是批量导入路由
if (req.method === "POST" && req.path.endsWith("/batch-import")) {
return batchLimiter(req, res, next);
} else if (req.method === "GET") {
// 读操作使用普通API限速
return apiLimiter(req, res, next);
} else if (
req.method === "POST" ||
req.method === "PUT" ||
req.method === "PATCH"
) {
// 写操作使用更严格的限速
return writeLimiter(req, res, next);
} else if (req.method === "DELETE") {
// 删除操作使用最严格的限速
return deleteLimiter(req, res, next);
}
// 其他方法使用API限速
return apiLimiter(req, res, next);
};