首页 > 解决方案 > /favicon.ico 在 Node JS 中登录后

问题描述

login/register在我的网站上使用 express(护照)创建了一个系统,并且在用户被重定向到登录页面之前保存了 originalUrl,但每次登录后,用户都被重定向到/favicon.ico 而不是保存的 Url。有人可以告诉我问题的原因是什么吗?

我的 app.use():

app.use((req, res, next) => {
    if (!['/login'].includes(req.originalUrl)) {
        req.session.returnTo = req.originalUrl;
    }
    res.locals.currentUser = req.user;
    res.locals.success = req.flash('success');
    res.locals.error = req.flash('error');
    next();
})

我的 /login 获取和发布请求:

app.get('/login', (req, res) => {
    res.render('login');
})

app.post('/login', passport.authenticate('local', { failureFlash: true, failureRedirect: '/login' }), (req, res) => {
    const redirectUrl = req.session.returnTo || '/';
    console.log(redirectUrl);
    delete req.session.returnTo;
    res.redirect(redirectUrl);
})

标签: htmlnode.jsexpressredirectfavicon

解决方案


您的会话中有两个传入请求之间的竞争条件。

您的app.use()中间件将看到/favicon.ico请求并将覆盖req.session.returnTo您的login路由可能刚刚设置的值。如果这两个请求一个接一个地出现(这可能是在浏览器第一次访问您的站点时),那么该/favicon.ico路由将弄乱您刚刚尝试使用该/login路由设置的会话状态。

我不知道该中间件试图做什么,但看起来它非常有能力覆盖会话中其他请求正在使用的内容。通过将最终的重定向 URL 放在查询参数中,登录后的重定向要安全得多。然后它在服务器上是无状态的,并且当有多个来自同一用户的服务器传入请求时,它不受这些类型的竞争条件的影响。


仅供参考,您还可以通过将此路由处理程序放在中间件之前相当容易地防止此特定问题(尽管不是其他潜在的竞争条件):

// put this before your middleware
app.get("/favicon.ico", (req, res) => {
    res.sendStatus(404);
    // or instead of a 404, send an actual favicon.ico file
    // just don't let routing continue to your middleware
});

这将使您的中间件在/favicon.ico被请求时根本无法运行,从而防止在特定位置导致与您的会话数据发生竞争条件。


推荐阅读