Node.js Passport登录和持久会话 背景
我有一个平均应用程序与CRUD功能充分测试邮递员。我一直试图坚持登录相当长一段时间了,现在没有运气。我已经阅读并尝试了以下内容Node.js Passport登录和持久会话 背景,node.js,session,authentication,express,passport.js,Node.js,Session,Authentication,Express,Passport.js,我有一个平均应用程序与CRUD功能充分测试邮递员。我一直试图坚持登录相当长一段时间了,现在没有运气。我已经阅读并尝试了以下内容 再加上一大堆其他轻松的阅读材料(很多问题) 但我只能注册和登录一个用户,不能持久登录会话 我的应用程序 是指向完整github repo的链接(如果您正在查找最新的更改,请检查开发分支) 我对Auth/Login的理解 下面是我对用户登录的理解,包括我的项目中的代码示例、postman结果的屏幕截图以及控制台日志 护照设置 我有以下auth.js文件,它配置
- 再加上一大堆其他轻松的阅读材料(很多问题)
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);
});
router.get('/checkauth', passport.authenticate('local'), function(req, res){
res.status(200).json({
status: 'Login successful!'
});
});
经邮递员测试,这条路线有效。我输入详细信息“joe”和“pass”,并得到以下响应
当点击此路由时,我们还可以在控制台中看到用户被序列化
那么接下来呢?
这就是我迷路的地方。我有几个问题
req.session.passport.user
发送回客户端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);
});
router.get('/checkauth', passport.authenticate('local'), function(req, res){
res.status(200).json({
status: 'Login successful!'
});
});
部分passport.authenticate('local')
(我想)是为了在授予对路由的访问权限之前测试用户会话是否存在,但我在运行该部分时从未得到200响应,即使是在登录之后
此路由是否期望头中传递一个req.session.passport.user
,或者作为需要auth的http请求上的数据参数
如果我遗漏了什么或者我理解错了什么,请告诉我,任何意见都是非常感谢的。谢谢大家。我不知道如何检查所有现有会话,但Passport正在处理会话ID的颁发。登录后,请尝试检查测试端点上是否有req.user,该用户现在是否正在我的服务器上进行会话? 不,您需要在
app.use(passport.session())之前使用express session
中间件
将会话实际存储在内存/数据库中。该中间件负责为浏览器设置cookie,并将浏览器发送的cookie转换为req.session
对象。PassportJS仅使用该对象进一步反序列化用户
我应该将req.session.passport.user发送回客户端吗?
如果您的客户在登录时需要用户
资源,那么您应该这样做。否则,我看不出有任何理由将用户对象发送到客户端
我是否需要未来所有请求的会话ID?
是,对于将来的所有请求,都需要会话id。但如果您的客户端是浏览器,则不需要发送任何内容。浏览器将会话id存储为cookie,并将其发送给所有后续请求,直到cookie过期express session
将读取该cookie,并将相应的会话对象附加为req.session
测试会话
passport.authenticate('local')
用于从邮件正文验证用户凭据。您应该仅在登录路径中使用此选项
但要检查用户是否在所有其他路由中经过身份验证,您可以检查是否定义了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!'
});
});
根据,req.user
将被设置为经过身份验证的用户。但是,为了使其正常工作,您需要快速会话
模块。你不应该需要任何东西,除了你已经有护照工作
就测试会话而言,您可以使用一个中间件功能来检查是否设置了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
});
正如@hassansin所说,您需要使用一个实现会话管理的中间件。session()中间件用于将passport框架连接到会话管理,而不是单独实现会话。您可以使用来实现会话管理。您需要按照以下方式修改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);
});
});
};
请注意,在本例中,会话引擎正在使用内存存储,如果您扩展应用程序并应用负载平衡,它将无法工作。当您达到这种开发状态时,将需要类似的东西
还请注意,您需要更改会话midleware调用中使用的机密值,并在所有应用程序实例上使用相同的值。Passport.js无法正常工作,因为它将会话存储在服务器中(错误且不可扩展)。您不希望在服务器中存储任何会话数据(保持无状态),因为这样您就可以扩展集群并处理更多请求 如果您查看Passport.js库中的代码,就不会有太多。。实际上,自己构建它可以更快、更高效
这是一个。不起作用的部分是“测试会话”部分。我已登录,但无法请求checkauth。但是如果我不发送会话id,路由如何知道im是正确的用户?有没有办法查看服务器上哪些会话处于活动状态?谢谢Hassansin,会话现在正在我的应用程序上运行。如果我在每个路由上使用req.isAuthenticated()而不是req.user来检查用户是否登录,会发生什么情况?那么,在节点应用程序重新启动后如何保持用户登录?因为现在它只是记忆中的一个片段session@hassansin和邮递员