2

我试图在一页上显示登录而不是用户的不同内容。

这是我用于生成 / 页面的代码:

app.get('/',function(req, res){
    if (!checkSession(req, res)) {
        res.render('index.ejs', {
            title: 'FrontSpeak - blog-based social network'
       })
    } else {
        res.render('index.ejs', {
            title: 'autrhorized'
        })
    }
})

检查会话功能:

function checkSession(req, res) {
if (req.session.user_id) {
    db.collection('users', function (err, collection) {
        collection.findOne({
            _id: new ObjectID(req.session.user_id)
        }, function (err, user) {
            if (user) {
                req.currentUser = user;
                return true;
            } else {
                return false;
            }
        });
    });
} else {
    return false;
}
}

登录功能:

app.post('/', function(req, res){
    db.collection("users", function (err, collection) {
        collection.findOne({ username: req.body.username }, function (err, doc) {
            if (doc && doc.password == req.body.password) {
                console.log("user found");
                req.session.user_id = doc._id;
            }
            }
        });
    });

});

所以,它似乎不起作用。但是,我认为这不是显示不同内容的最佳方式。可能有一些更优雅的方法来做到这一点?谢谢!

更新:新的登录功能:

app.post('/', function(req, res){
    db.collection("users", function (err, collection) {
        collection.findOne({ username: req.body.username }, function (err, doc) {
            console.log('found user');
            if (doc && doc.password == req.body.password) {
                req.session.user_id = doc._id;
                res.redirect('/');
            };
            res.redirect('/');
        });
    res.redirect('/');  
    });
});
4

2 回答 2

3

这是一个尝试将传统的同步模型应用到 Node 的异步回调驱动模型的案例。

数据库查询完成后,您返回true,但您只是返回到数据库驱动程序。 checkSession很久以前回来了。由于如果有(如果没有)该函数返回未定义,登录检查将始终评估为假。session.user_idfalse

相反,您可以使用 Brandon 的建议进行checkSession异步,或者我建议实现中间件功能:

function checkLogin(req, res, next) {
    if (req.session.user_id) {
        db.collection('users', function (err, collection) {
            if (err) return next(err); // handle errors!
            collection.findOne({
                _id: new ObjectID(req.session.user_id)
            }, function (err, user) {
                if (user) {
                    req.currentUser = user;
                } else {
                    req.currentUser = null;
                }
                next();
            });
        });
    } else {
        req.currentUser = null;
        next();
    }
}

现在您有两种使用中间件功能的方法。如果您想在每个请求中检查用户,只需将其添加到应用程序中:

app.use(checkLogin);

现在每个请求都会有一个req.currentUser,但是您会为每个请求从数据库中获取登录状态带来性能损失。或者,如果您只需要某些请求的用户信息,请将函数粘贴在路由中:

app.get('/', checkLogin, function(req, res) {
    if (req.currentUser) {
        // logged in
    } else {
        // not
    }
});

您可以在Express 文档中了解更多相关信息。

于 2012-07-06T18:25:24.240 回答
0

看起来您正试图checkSession通过检查其返回值来用作同步函数,但checkSession不能同步,因为它依赖于异步功能,即此处的回调:db.collection('users', function (err, collection) .... 您需要修改checkSession为异步:

function checkSession(req, res, callback) {
if (req.session.user_id) {
    db.collection('users', function (err, collection) {
        collection.findOne({
            _id: new ObjectID(req.session.user_id)
        }, function (err, user) {
            if (user) {
                req.currentUser = user;
                callback(true);
            } else {
                callback(false);
            }
        });
    });
} else {
    callback(false);
}
}

然后在您的请求处理程序中异步使用它:

app.get('/',function(req, res){
    checkSession(req, res, function(isUser) {
      if (!isUser) {
          res.render('index.ejs', {
              title: 'FrontSpeak - blog-based social network'
         })
      } else {
          res.render('index.ejs', {
              title: 'autrhorized'
          })
      }
    });
})
于 2012-07-06T18:17:33.813 回答