背景
我有一个用postman完全测试过的CRUD功能的应用程序。我已经尝试坚持登录了相当长的一段时间,但没有运气。我已经阅读并尝试了以下内容
但我只能注册和登录用户,不能使用会话持久化登录。
我的应用程序
Here是完整github存储库的链接(如果您正在查找最新的更改,请查看开发分支)
我对身份验证/登录的理解
以下是我对用户登录的理解,以及我项目中的代码示例和postman结果的屏幕截图以及控制台日志。
Passport设置
我有以下auth.js文件,它配置了passport
var passport = require('passport');
var LocalStrategy = require('passport-local').Strategy;
module.exports = function(app, user){
app.use(passport.initialize());
app.use(passport.session());
// passport config
passport.use(new LocalStrategy(user.authenticate()));
passport.serializeUser(function(user, done) {
console.log('serializing user: ');
console.log(user);
done(null, user._id);
});
passport.deserializeUser(function(id, done) {
user.findById(id, function(err, user) {
console.log('no im not serial');
done(err, user);
});
});
};
这在服务器文件中被调用,如下所示
//code before
var user = require('./models/user.js');
var auth = require('./modules/auth.js')(app, user);
// code after
用于登录的路由
在我的路由中,我有如下登录路由
router.post('/login', function(req, res, next) {
passport.authenticate('local', function(err, user, info) {
if (err) {
return next(err);
}
if (!user) {
return res.status(401).json({
err: info
});
}
req.logIn(user, function(err) {
if (err) {
return res.status(500).json({
err: 'Could not log in user'
});
}
res.status(200).json({
status: 'Login successful!'
});
});
})(req, res, next);
});
根据邮递员的测试,此路由工作正常。我输入详细信息'joe‘和'pass’并得到以下响应。
当命中此路由时,我们还可以在控制台中看到用户已被序列化。
那么下一步呢?
这就是我迷路的地方。我有几个问题。
在我的server?
req.session.passport.user
发送回客户端?
测试会话
我有第二个用于测试会话的路由设置,如下所示
router.get('/checkauth', passport.authenticate('local'), function(req, res){
res.status(200).json({
status: 'Login successful!'
});
});
部分passport.authenticate('local')
(我认为)是为了在提供对路由的访问权限之前测试用户会话是否存在,但我在运行此命令时从未得到200响应,即使在登录之后也是如此。
此路由是否期望在head中传递req.session.passport.user
,或者作为需要身份验证的http请求的数据参数?
如果我遗漏了什么或理解错了什么,请告诉我,任何意见都是感谢的。谢谢大家。
发布于 2016-04-10 17:20:40
现在是我的服务器上的会话中的用户吗
不需要,您需要在app.use(passport.session());
之前使用express-session
中间件将会话实际存储在内存/数据库中。该中间件负责向浏览器设置cookies,并将浏览器发送的cookies转换为req.session
对象。PassportJS只使用该对象来进一步反序列化用户。
是否应该将req.session.passport.user发送回客户端?
如果您的客户端在登录时需要user
资源,那么您应该这样做。否则,我看不到任何将user对象发送到客户端的理由。
将来的所有请求都需要会话ID吗?
是的,对于将来的所有请求,会话id都是必填项。但是如果你的客户端是一个浏览器,你不需要发送任何东西。浏览器将会话id存储为cookie,并将其发送给所有后续请求,直到cookie过期。express-session
将读取该cookie并将相应的会话对象附加为req.session
。
测试会话的
passport.authenticate('local')
用于从POST正文验证用户凭据。您应该仅对登录路由使用此选项。
但是要检查用户是否在所有其他路由上进行了身份验证,您可以检查是否定义了req.user
。
function isAuthenticated = function(req,res,next){
if(req.user)
return next();
else
return res.status(401).json({
error: 'User not authenticated'
})
}
router.get('/checkauth', isAuthenticated, function(req, res){
res.status(200).json({
status: 'Login successful!'
});
});
发布于 2016-04-15 00:53:48
正如@hassansin所说,您需要使用实现会话管理的中间件。passport.session()中间件用于将passport框架连接到会话管理,而不是自己实现会话。您可以使用express-session
middleware来实现会话管理。您需要通过以下方式修改auth.js
var passport = require('passport');
var session = require('express-session');
var LocalStrategy = require('passport-local').Strategy;
module.exports = function(app, user){
app.use(session({secret: 'some secret value, changeme'}));
app.use(passport.initialize());
app.use(passport.session());
// passport config
passport.use(new LocalStrategy(user.authenticate()));
passport.serializeUser(function(user, done) {
console.log('serializing user: ');
console.log(user);
done(null, user._id);
});
passport.deserializeUser(function(id, done) {
user.findById(id, function(err, user) {
console.log('no im not serial');
done(err, user);
});
});
};
请注意,在这种情况下,会话引擎使用的是内存中的存储,如果您扩展应用程序并应用负载平衡,它将不起作用。当您达到这种开发状态时,将需要像connect-redis
session store这样的东西。
还要注意,您需要更改会话中间件调用中使用的保密值,并在所有应用程序实例上使用相同的值。
发布于 2016-04-14 00:08:41
根据passport documentation,req.user
将设置为经过身份验证的用户。但是,为了使其正常工作,您将需要express-session
模块。除了已有的东西外,您不需要任何其他东西即可使passport正常工作。
就测试会话而言,您可以使用一个中间件功能来检查是否设置了req.user,如果设置了,我们就知道用户已通过身份验证,如果没有,您可以重定向用户。
例如,您可以有一个中间件函数,可以在任何想要进行身份验证的路由上使用它。
authenticated.js
module.exports = function (req, res, next) {
// if user is authenticated in the session, carry on
if (req.user) {
next();
}
// if they aren't redirect them to the login page
else {
res.redirect('/login');
}
};
控制器
var authenticated = require('./authenticated');
router.get('/protectedpage', authenticated, function(req, res, next) {
//Do something here
});
https://stackoverflow.com/questions/36486397
复制相似问题