问题描述
这是我的快递代码:
(Host\s[a-zA-Z0-9-!\*]+)\n)
这是我的中间件:
res.setHeader('Content-Type','application/json');
if (req.query.uuid) {
db.getPlayerByUUID(req.query.uuid,(data) => {
res.send(data)
})
} else if (req.query.name != null) {
db.getPlayerByName(req.query.name,(data) => {
res.send(data)
})
}
}).use(rateLimiter(req))
那么我如何将我的 IP 发送到我的中间件或检查我的快速代码中的 IP 并仅在该 IP 不在我的白名单文件中时使用它?这个问题让我很伤心:/。
对不起,如果我的问题很愚蠢,我以前从未真正与 express 合作过。
解决方法
看起来您的主要问题在这里:
}).use(rateLimiter(req))
您没有准确显示之前的内容,但如果这是一个 app.use()
或 router.use()
,那么您需要修正将中间件传递给它的方式,如下所示:>
app.use(rateLimiter)
这会将中间件函数 rateLimiter
传递给 app.use()
,以便稍后调用。所有中间件都使用三个参数 (req,res,next)
调用,因此,您需要修改中间件以匹配它。
然后,您需要在中间件中适当地使用这些参数来实现您的目标。这是一个可能的实现,它应该向您展示这是如何工作的。
// create middleware from your rate limiting package to later conditionally apply
const limiter = rateLimit({
windowMs: 60 * 1000,max: config.webserver.limit,message: {error: 'You have exceeded the requests in 1 min limit! Please try again soon.'},headers: true,})
const rateLimiter = (req,next) => {
const ip = req.headers['x-forwarded-for'] || req.connection.remoteAddress;
// implement your ip address limiting here
// you should have one of three outcomes
// 1. You call next() to allow the routing to continue for this request
// 2. You call next(someError) to abort routing and fall-through to
// your Express error handler
// 3. You send a response using something like res.status(xxx).send(),// thus ending the request
// block this request if the IP address is on the blacklist
if (blacklist.indexOf(ip) >= 0) {
res.status(403).send('You cannot use this service!');
return;
}
// if the IP address is on the whitelist,then let it go
if (whitelist.indexOf(ip) >= 0) {
// continue routing
next();
return;
}
// apply rate limiter middleware
limiter(req,next);
}
app.use(rateLimiter);
这会在此处创建一个名为 limiter
的中间件和一个中间件 rateLimiter
。 rateLimiter
中间件将通过 app.use(rateLimiter)
在每个请求传入请求上调用。然后,在里面它会检查黑名单和白名单。如果它在黑名单上,它将使请求短路并以 403 结束它。如果它在白名单上,它将继续路由并让后续的路由处理程序处理它。如果它不在任一列表中,则它会通过手动调用速率限制中间件并将已传递到中间件的 (req,next)
传递给它,有条件地对其应用速率限制。
对您提出的问题的其他评论:
我需要为除少数IP之外的每个人申请中间件,但我无法在路由之外获取req和res,我该如何申请?
req
和 res
仅存在于处理给定传入请求的过程中。因此,一旦请求结束,与该请求关联的那些对象将被垃圾收集并且不再可用。即使您设法将它们塞到某处,这对您也无济于事,因为与 res
对象关联的套接字已完成并且可能已关闭,您无法继续向任何人发送更多数据。
因此,除了处理路由或中间件之外,您无法访问 req
和 res
。这就是它们可用且有用的地方。
那么我如何将我的 IP 发送到我的中间件或检查我的快速代码中的 IP 并仅在该 IP 不在我的白名单文件中时使用它?这个问题害死我了
传入请求的 IP 地址在 req
对象中可用。您的中间件可以访问它。
通常的做法是:
const ip = req.headers['x-forwarded-for'] || req.connection.remoteAddress;
关于 here 的更多讨论,但从您的代码来看,您似乎已经知道这一点。