如何使用NodeJS/ExpressJS进行登录重定向

3
我正在寻找一种方法,在成功登录后将用户重定向到他或她之前所在的页面。例如,如果用户想使用仅限会员访问的功能,他或她将被重定向到登录页面,并在成功登录后,将被重定向回用户尝试在登录之前访问的页面。这是我目前的进展:
中间件:
function requireLogin(req, res, next){
    if (!req.user) res.redirect('/login');
    else next();
}

登录:

app.post('/login', function(req,res){
    User.findOne({email: req.body.email}, function(err, user){
            if (!user) res.render('login.jade',{error: 'Invalid email or password.'});
            else{
                    if (bcrypt.compareSync(req.body.password,user.password)) {
                            req.session.user = user; //set cookie session
                            res.redirect('/forums');
                    }
                    else res.render('login.jade',{error: 'Invalid email or password.'});
            }
    });
});

示例路由:

app.post('/article/comment', requireLogin, function(req,res){...

我看过一些关于这个主题的SO帖子,但是没有真正有资格的答案(尤其是没有PassportJS的情况下)。有什么建议吗?

3个回答

3
我能通过对现有代码进行几个简单的补充来解决这个问题:
function requireLogin(req, res, next){
    if (!req.user) {
            req.session.prevUrl = req.body.url;
            if(req.xhr) res.send({"err":"usrErr"});
            else res.redirect('/login');
    }
    else next();
}

app.post('/login', function(req,res){
    User.findOne({email: req.body.email}, function(err, user){
            if (!user) res.render('login.jade',{error: 'Invalid email or password.'});
            else{
                    if (bcrypt.compareSync(req.body.password,user.password)) {
                            req.session.user = user; //set cookie session
                            if(req.session.prevUrl) res.redirect(req.session.prevUrl);
                            else res.redirect('/forums');
                    }
                    else res.render('login.jade',{error: 'Invalid email or password.'});
            }
    });
});

我将一个用户在尝试访问仅对会员开放的功能时所在页面保存为会话数据。请注意,这比“返回”解决方案要好得多,因为(例如,如果用户输入了错误的登录信息,则以前的页面现在不会是登录页面,而是保存在会话中的页面)。现在已经保存了会话存储,可以在登录时进行简单的检查,以查看是否存在保存的会话URL。如果存在,则重定向到保存的会话URL,否则重定向到默认主页。
P.S.该行if(req.xhr) res.send({"err:"usrErr"}); 是用于检查请求是否是JQuery请求。这是因为如果请求是通过JQuery发出的,则不会执行重定向。err响应允许我在我的JQuery函数中进行简单的检查,如果用户不存在,则执行重定向。请注意,在这种情况下仍然保存会话数据,因此只需在脚本中添加window.location.href='/login'即可执行重定向。
感谢@mikeyhew指导我朝正确的方向前进。

1

如果您存储了requireLogin中间件的请求URL以备将来使用,会很有帮助:

function requireLogin(req, res, next){
    if (!req.user) {
      var postLoginRedirectUrl = req.originalUrl;
      // store this url somehow (session or query params?)
      res.redirect('/login');
    } else {
      next();
    }
}

我看到有些网站使用查询参数;你只需要确保在登录过程中不会丢失URL。
然后,当用户成功登录时,只需将他们重定向到该URL。

@Nindaff,我认为使用express-back的问题在于,如果登录过程涉及到多个URL更改,用户将被重定向回登录流程。在这种情况下,有意保存URL到会话中会更加有韧性和未来方向感。 - Michael Hewson
感谢您的输入!虽然它受到这个问题的启发,但它实际上更是http referer头的解决方案。 - undefined
正如我的原始帖子所示,我实际上已经在使用cookies了。也许可以尝试类似这样的代码 "req.session.prevUrl=req.originalUrl"; 然后在登录路由中执行 " if (req.session.prevUrl) res.redirect(req.session.prevUrl); else res.redirect('/dashboard')"。你们觉得呢? - cg14

1
您可以使用res.redirect('back'),唯一的注意事项是它依赖于不可靠的http-referer头,当省略http-referer头时,它默认为/。请查看文档

我曾考虑过那种方法,但对我个人来说似乎不太可靠。不过还是谢谢你的建议。 - cg14
这启发了我编写一个中间件,请查看 express-back - undefined

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接