使用 Passportjs 刷新页面后保持身份验证
Staying authenticated after the page is refreshed using Passportjs
我正在使用 express、mongoose 和 passportjs.[=17 构建 SPA =]
我为我的用户创建了一个简单的架构:
var mongoose = require('mongoose');
var Schema = mongoose.Schema;
var passportLocalMongoose = require('passport-local-mongoose');
var User = new Schema({
username: String,
password: String,
first_name: String
}, { collection: 'users' });
User.plugin(passportLocalMongoose);
mongoose.model('User', User);
使用 mongoose 给我的 User
对象配置护照:
passport.use(new LocalStrategy(User.authenticate()));
passport.serializeUser(User.serializeUser());
passport.deserializeUser(User.deserializeUser());
并将我的应用配置为在导航到此路线时对用户进行身份验证:
app.post('/login', passport.authenticate('local'), function(req, res, next) {
if (req.isAuthenticated()) {
return res.json({ state: 'success', user: { first_name: req.user.first_name } });
}
return res.json({ state: 'failure', message: 'cannot authenticate' });
});
现在我可以成功验证用户身份了。并且浏览器会保存一个会话 ID cookie。
我的问题是,每次用户刷新页面时,passport 都不会使用会话 ID 反序列化用户,这导致用户未通过身份验证。
访问站点根目录中的 req.user
对象时,我得到 undefined
让我意识到护照没有正确反序列化用户的原因:
app.use('/', function (req, res, next) {
console.log(req.user); // prints undefined.
next();
});
刷新页面后恢复用户的正确方法是什么?
看着你的 post 我可以猜出问题出在哪里。有问题你已经粘贴了你的后端 expressjs 代码,但问题发生在前端。
想一想当您处理普通 javascript 文件时的情况,您使用 firebug n 的 Chrome 开发工具对变量值进行了一些编辑。假设您刷新页面,您是否仍然在视图中看到相同的编辑值?没有权利。您的观点也是如此,您是临时持有用户数据。尽管您的后端保留 req.user 中的值,但您的前端在刷新时会丢失它。
因此您必须执行以下两个操作之一:
- 成功登录时将您的值存储在 cookie 中,并在成功登录时将其删除
登出。这样 cookie 就永远不会丢失数据,即使你
刷新页面。需要时从该 cookie 访问用户数据
- 调用后端 API returns 值 req.user 在你的每个
页面刷新
我不确定你为 SPA 使用的是什么前端框架,如果你使用 AngularJS 那么你可以使用 cookieStore 服务它干得漂亮。
解决方案是将会话存储在 DB 中。我用了 connect-mongo.
app.js:
var mongoose = require('mongoose');
var expressSession = require('express-session');
var MongoStore = require('connect-mongo')(expressSession);
mongoose.connect(db_url, function (err) {
if (err) {
console.log(err);
}
});
app.use(expressSession({
secret: process.env.SESSION_SECRET || 'keyboard cat',
resave: false,
saveUninitialized: false,
store: new MongoStore({ mongooseConnection: mongoose.connection })
}));
此后,即使在刷新页面后,每个请求也会 req.isAuthenticated()
returns true
。 (感谢 app.use(passport.session())
出现在任何路由处理程序之前)
app.use('/', function (req, res, next) {
if (req.isAuthenticated()) {
// returns true if a user already logged in.
}
next();
});
我正在使用 express、mongoose 和 passportjs.[=17 构建 SPA =]
我为我的用户创建了一个简单的架构:
var mongoose = require('mongoose');
var Schema = mongoose.Schema;
var passportLocalMongoose = require('passport-local-mongoose');
var User = new Schema({
username: String,
password: String,
first_name: String
}, { collection: 'users' });
User.plugin(passportLocalMongoose);
mongoose.model('User', User);
使用 mongoose 给我的 User
对象配置护照:
passport.use(new LocalStrategy(User.authenticate()));
passport.serializeUser(User.serializeUser());
passport.deserializeUser(User.deserializeUser());
并将我的应用配置为在导航到此路线时对用户进行身份验证:
app.post('/login', passport.authenticate('local'), function(req, res, next) {
if (req.isAuthenticated()) {
return res.json({ state: 'success', user: { first_name: req.user.first_name } });
}
return res.json({ state: 'failure', message: 'cannot authenticate' });
});
现在我可以成功验证用户身份了。并且浏览器会保存一个会话 ID cookie。
我的问题是,每次用户刷新页面时,passport 都不会使用会话 ID 反序列化用户,这导致用户未通过身份验证。
访问站点根目录中的 req.user
对象时,我得到 undefined
让我意识到护照没有正确反序列化用户的原因:
app.use('/', function (req, res, next) {
console.log(req.user); // prints undefined.
next();
});
刷新页面后恢复用户的正确方法是什么?
看着你的 post 我可以猜出问题出在哪里。有问题你已经粘贴了你的后端 expressjs 代码,但问题发生在前端。
想一想当您处理普通 javascript 文件时的情况,您使用 firebug n 的 Chrome 开发工具对变量值进行了一些编辑。假设您刷新页面,您是否仍然在视图中看到相同的编辑值?没有权利。您的观点也是如此,您是临时持有用户数据。尽管您的后端保留 req.user 中的值,但您的前端在刷新时会丢失它。
因此您必须执行以下两个操作之一:
- 成功登录时将您的值存储在 cookie 中,并在成功登录时将其删除 登出。这样 cookie 就永远不会丢失数据,即使你 刷新页面。需要时从该 cookie 访问用户数据
- 调用后端 API returns 值 req.user 在你的每个 页面刷新
我不确定你为 SPA 使用的是什么前端框架,如果你使用 AngularJS 那么你可以使用 cookieStore 服务它干得漂亮。
解决方案是将会话存储在 DB 中。我用了 connect-mongo.
app.js:
var mongoose = require('mongoose');
var expressSession = require('express-session');
var MongoStore = require('connect-mongo')(expressSession);
mongoose.connect(db_url, function (err) {
if (err) {
console.log(err);
}
});
app.use(expressSession({
secret: process.env.SESSION_SECRET || 'keyboard cat',
resave: false,
saveUninitialized: false,
store: new MongoStore({ mongooseConnection: mongoose.connection })
}));
此后,即使在刷新页面后,每个请求也会 req.isAuthenticated()
returns true
。 (感谢 app.use(passport.session())
出现在任何路由处理程序之前)
app.use('/', function (req, res, next) {
if (req.isAuthenticated()) {
// returns true if a user already logged in.
}
next();
});