Passport+Express-Session认证异常:req.user未定义且req.isAuthenticated()非函数
Passport LocalStrategy认证异常:req.user未定义且req.isAuthenticated()不存在
问题详情
我使用Passport结合express-session实现身份认证,采用LocalStrategy。Passport的deserializeUser函数能正常获取到用户,但回调函数done要么没能设置req.user,要么在执行setUserAuthentication中间件(该中间件负责将res.locals.user设为req.user)之前,req.user就被清除了。
我查阅了大量同类问题,了解到需要保证中间件顺序正确,目前我的中间件顺序看起来没问题:在session、passport.initialize()、passport.session()之后才挂载路由。
服务器代码(index.js)
app.use(express.urlencoded({extended : false})); app.use(cookieParser()); app.use(express.static('./assets')); app.use(layout); app.set('view engine' , 'ejs'); app.set('views','./views'); app.set('layout','./layouts'); app.use(session({ name : 'user_key', secret : 'anything', saveUninitialized : false, resave : false, cookie : { maxAge : (1000*60*100) } })); app.use(passport.initialize()); app.use(passport.session()); app.use(passport.setUserAuthentication); app.use('/' , require('./routes'));
Passport配置文件(config/passport-local-strategy.js)
const passport = require('passport'); const LocalStrategy = require('passport-local').Strategy; const User = require('../models/user'); passport.use(new LocalStrategy( { usernameField : 'email' }, function(email , password , done){ User.findOne({email : email},function(err , user){ if(err){ console.log('error in finding user'); return done(err); } if(!user || user.password != password){ console.log('invalid credentials'); return done(null,false); } return done(null,user); }) } )) passport.serializeUser(function(user,done){ done(null,user.id); }); passport.deserializeUser(function(id,done){ // console.log(id); User.findById(id,(err,user)=>{ if(err){ console.log('error in finding user'); return done(err); } return done(null,user); }) }); passport.checkAuthentication = function(res,req,next){ if(req.isAuthenticated()){ return next(); } else res.redirect('/users/sign-in'); } passport.setUserAuthentication = function(res,req,next){ if(req.isAuthenticated()){ res.locals.user = req.user; } next(); } module.exports = passport;
目录结构
config / passport-local-strategy.js controller/user_handler.js routes/user.js index.js(服务器入口)
当前报错
req.user is undefined 且 req.isAuthenticated() is not a function
解决办法
问题出在自定义中间件的参数顺序错误:Express中间件的标准参数顺序是 (req, res, next),但你写的checkAuthentication和setUserAuthentication把res放在了第一个参数的位置。
这会导致:
- 你调用的
req.isAuthenticated()实际上是在res对象上调用,而res并没有这个方法,所以报错req.isAuthenticated() is not a function。 - 你访问的
req.user实际是res对象,自然返回undefined,无法正确赋值给res.locals.user。
修正后的中间件代码:
passport.checkAuthentication = function(req, res, next){ if(req.isAuthenticated()){ return next(); } res.redirect('/users/sign-in'); } passport.setUserAuthentication = function(req, res, next){ if(req.isAuthenticated()){ res.locals.user = req.user; } next(); }
另外提醒:当前session配置使用默认的内存存储,生产环境下会导致内存泄漏,建议更换为如connect-mongo这类持久化存储方案,但这不是本次报错的直接原因。
内容的提问来源于stack exchange,提问作者Vivek
相关产品推荐
相关产品推荐

