我需要为每个人应用中间件,除了几个 IP,但我无法在路由之外获得 req 和 res,我该如何应用它?

问题描述

这是我的快递代码

(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 的中间件和一个中间件 rateLimiterrateLimiter 中间件将通过 app.use(rateLimiter) 在每个请求传入请求上调用。然后,在里面它会检查黑名单和白名单。如果它在黑名单上,它将使请求短路并以 403 结束它。如果它在白名单上,它将继续路由并让后续的路由处理程序处理它。如果它不在任一列表中,则它会通过手动调用速率限制中间件并将已传递到中间件的 (req,next) 传递给它,有条件地对其应用速率限制。


对您提出的问题的其他评论:

我需要为除少数IP之外的每个人申请中间件,但我无法在路由之外获取req和res,我该如何申请?

reqres 仅存在于处理给定传入请求的过程中。因此,一旦请求结束,与该请求关联的那些对象将被垃圾收集并且不再可用。即使您设法将它们塞到某处,这对您也无济于事,因为与 res 对象关联的套接字已完成并且可能已关闭,您无法继续向任何人发送更多数据。

因此,除了处理路由或中间件之外,您无法访问 reqres。这就是它们可用且有用的地方。

那么我如何将我的 IP 发送到我的中间件或检查我的快速代码中的 IP 并仅在该 IP 不在我的白名单文件中时使用它?这个问题害死我了

传入请求的 IP 地址在 req 对象中可用。您的中间件可以访问它。

通常的做法是:

const ip = req.headers['x-forwarded-for'] || req.connection.remoteAddress;

关于 here 的更多讨论,但从您的代码来看,您似乎已经知道这一点。