mirror of
https://github.com/ZeroCatDev/ClassworksKV.git
synced 2025-07-01 20:09:23 +00:00
108 lines
3.6 KiB
JavaScript
108 lines
3.6 KiB
JavaScript
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);
|
||
};
|