如何在Passport.js LocalStrategy中获取认证失败错误信息?
如何在Passport LocalStrategy认证失败后访问错误消息?
我设置了Passport的LocalStrategy来处理用户登录认证,并且在认证失败时返回了自定义错误消息,但不知道怎么在failureRedirect指向的路由中获取这些消息。
我的LocalStrategy代码:
passport.use( new LocalStrategy({usernameField:'email'},(email,pass,done)=>{ console.log(pass); user.findOne({email:email}).then(user=>{ if(!user){ return done(null,false,{message:"the email is not registered"}) } bcrypt.compare(pass,user.pass,(err,isMatched)=>{ if(err){throw err} if(isMatched){ return done(null,user); } else{ return done(null,false,{message:"incorrect password"}) } }) }).catch(e=>console.log(e)) }) )
我的登录路由代码:
app.post("/login",async function(req,res,next){ passport.authenticate('local',{ successRedirect:'/', failureRedirect:"/register" })(req,res,next); })
现在需要解决的是:当认证失败跳转到/register时,如何获取我在done函数里设置的message?
要获取这些认证失败的错误消息,你有两种常用的方案,具体如下:
方案1:使用Flash消息(推荐)
Passport支持配合express-flash中间件来传递临时消息,步骤如下:
- 首先安装并配置express-flash和express-session(因为flash依赖session):
npm install express-flash express-session
- 在你的Express应用中配置中间件:
const session = require('express-session'); const flash = require('express-flash'); // 先配置session,flash依赖它 app.use(session({ secret: 'your-secret-key-here', // 替换成你的自定义密钥 resave: false, saveUninitialized: false })); app.use(flash());
- 修改登录路由的Passport配置,开启
failureFlash选项:
app.post("/login",async function(req,res,next){ passport.authenticate('local',{ successRedirect:'/', failureRedirect:"/register", failureFlash: true // 开启后,Passport会自动把错误消息存入flash容器 })(req,res,next); })
- 在
/register路由对应的模板或响应中访问flash消息:
如果你用EJS模板,可以这样渲染:
<% if (messages.error) { %> <div class="error-notice"><%= messages.error %></div> <% } %>
如果是直接在路由逻辑中处理,可通过req.flash('error')获取:
app.get('/register', (req, res) => { // 取出第一条错误消息(flash消息是数组格式) const errorMsg = req.flash('error')[0]; res.render('register', { error: errorMsg }); });
方案2:自定义认证回调,手动传递消息
如果你不想依赖flash中间件,也可以自定义Passport的回调函数,手动把错误消息通过URL参数或session传递:
修改登录路由:
app.post("/login",async function(req,res,next){ passport.authenticate('local', (err, user, info) => { if (err) { return next(err); } if (!user) { // info对象就是你在done函数中传递的{message: "..."} return res.redirect(`/register?error=${encodeURIComponent(info.message)}`); } req.logIn(user, (err) => { if (err) { return next(err); } return res.redirect('/'); }); })(req,res,next); })
然后在/register路由中获取URL参数:
app.get('/register', (req, res) => { const errorMsg = req.query.error ? decodeURIComponent(req.query.error) : null; res.render('register', { error: errorMsg }); });
注意:URL参数传递消息的方式会把内容暴露在地址栏,敏感场景更推荐用flash或session存储。
内容的提问来源于stack exchange,提问作者Vikram
相关产品推荐
相关产品推荐

