我的Angular - Express + Passport行为有一种奇怪的行为。
在我的应用程序中,用户通过以下方式进行身份验证:AngularJS应用程序调用链接到NTML的外部服务,该服务返回多个信息,例如当前用户的电子邮件。
然后,AngularJS应用程序在我的Express后端(/rest/userProfile
)上调用REST服务以获取用户的完整配置文件。那是我在后端验证用户的时候。
然而,与此同时,AngularJS应用程序(在其初始化期间)在我的后端调用其他几个REST api(例如检索/rest/config
中的应用程序配置,以及在主页上显示的其他一些内容)。这些来电不受保护,通常在<{>>之前处理/rest/userProfile
。
换句话说,Express会话是由后端收到的第一个请求创建的,通常是/rest/config
而不是/rest/userProfile
(我认为这一点非常重要)。
在完成所有初始化之后,用户可以调用一些受保护的REST api,例如/rest/foo/
。
但似乎有时,然后在后端无法识别用户,尽管请求包含Express cookie(connect.sid
)。日志显示请求对象不包含passport
属性。
如果我刷新浏览器的一两次,一切都开始正常工作,即用户最终被识别。在那之后,在某些时候,我可以重启我的浏览器,它可以直接工作而没有问题。
似乎如果我延迟所有请求(如/rest/config
)以确保/rest/userProfile
是服务器上收到的第一个请求,则一切正常(即用户将在受保护时正确识别)路由)。
/rest/userProfile
的调用作为后端收到的第一个请求,因此Passport创建的会话将包含用户信息?
/rest/userProfile
的呼叫(当然在任何受保护路线之前)?代码
在我的index.js
上,我设置了以下Express中间件:
app.use(session({
secret: 'xxx',
resave: true,
saveUninitialized: true
}));
app.use(passport.initialize());
app.use(passport.session());
在我的主要路线JS文件:
passport.serializeUser(function(user, done) {
console.log('[serialize user]', user);
done(null, user.username);
});
passport.deserializeUser(function(username, done) {
console.log('[deserialize username]', username);
User.findOne({username: username}, function(err, user) {
done(err, user);
});
});
passport.use('ntml-strategy', new LocalStrategy({
usernameField: 'mail',
passwordField: 'password',
passReqToCallback: true
},
function(req, username, password, done) {
console.log('[ntml strategy]', username);
User.findOne({username: username}, function(err, user) {
if (err) {
return done(err);
} else if (user && user !== null) {
return done(null, user);
}
// User does not exist in DB.
// We should create a new user with data received from client.
var newUser = new User({
username: username,
roles: ['user']
});
User.create(newUser, function(err, userSaved) {
if (err) {
return done(err);
}
return done(null, userSaved);
});
});
}));
// The REST api to get user profile
app.post('/rest/userProfile', passport.authenticate('ntml-strategy'), getUserProfile);
function getUserProfile(req, res) {
var user = req.user;
console.log('[getUserProfile]', user);
if (!user) {
return res.status(401).end();
}
res.json({
username: user.username,
roles: user.roles
});
}
// In other file, another route:
app.get('/rest/foo/', isAuthenticated, getUserStuff);
function isAuthenticated(req, res, next) {
if (!req.isAuthenticated()) {
return res.status(401).end();
}
next();
}
function getUserStuff(req, res, next) {
// Do stuff
}
在User
模型上,我设置了passport-local-mongoose
:
User.plugin(passportLocalMongoose, {
usernameField: 'username',
usernameUnique: true
});
请注意,删除该插件不会改变行为中的任何内容。
感谢。
对于版本:节点5.5,快递4.10.8,护照0.3.2,护照本地1.0.0和Angular 1.5。