如何修改Passport.js默认未授权响应,在EJS前端展示登录错误?
解决Passport本地登录失败时自定义错误显示问题
问题背景
基于NodeJS、Express、MongoDB开发的项目,已配置Passport.js的local-login策略及/login路由。登录失败(用户名或密码错误)时出现显示“Unauthorized”的黑屏,使用EJS作为前端模板,需要修改Passport默认的未授权响应,在前端页面展示自定义错误信息。
解决方案步骤
1. 调整Passport认证策略的错误处理
统一使用req.flash存储错误信息,确保错误能传递到前端页面:
passport.use( "local-login", new LocalStrategy( { usernameField: "email", passwordField: "password", passReqToCallback: true, }, async (req, email, password, done) => { try { const user = await User.findOne({ email: email }); if (!user) { req.flash("error", "Adresa de email nu este înregistrată."); return done(null, false); } const isMatch = await user.matchPassword(password); if (!isMatch){ req.flash("error", "Parola introdusă este incorectă."); return done(null, false); } if (user.role === "admin") { user.isAdmin = true; } req.session.user = user; return done(null, user); } catch (error) { console.log(error); req.flash("error", "Eroare la autentificare. Încercați din nou."); return done(error, false); } } ) );
2. 修改登录路由的Passport认证配置
在passport.authenticate中添加failureRedirect: '/login',指定登录失败后跳转回登录页面,避免默认的401黑屏:
router.post("/login", passport.authenticate("local-login", { failureRedirect: '/login', failureMessage: true }), async (req, res, next) => { const comenzi = await Comanda.find({ utilizator: req.user.username }).sort({ createdAt: 'desc' }); res.cookie("user", req.user, { maxAge: 3600000, httpOnly: true, secure: false }); jwt.sign( { user: req.user }, "secretKey", { expiresIn: "1h" }, (err, token) => { if (err) { req.flash("error", "Eroare la generarea tokenului."); return res.redirect("/login"); } res.render("login", { user: req.user, messages: req.flash(), comenzi: comenzi }); } ); });
3. 在EJS登录模板中渲染错误信息
在登录页面的EJS模板里添加错误展示逻辑,比如放在表单上方:
<% if (messages && messages.error) { %> <div class="alert alert-danger"> <%= messages.error %> </div> <% } %> <!-- 登录表单代码 --> <form action="/login" method="POST"> <div> <label>Email:</label> <input type="email" name="email" required> </div> <div> <label>Parola:</label> <input type="password" name="password" required> </div> <button type="submit">Autentificare</button> </form>
4. 确认核心中间件配置(必做)
确保Express应用已配置会话和flash中间件,否则req.flash无法正常工作:
const session = require('express-session'); const flash = require('connect-flash'); // 会话配置(需放在Passport配置之前) app.use(session({ secret: 'your-custom-secret-key', // 替换为你的私密密钥 resave: false, saveUninitialized: false })); // 启用flash消息 app.use(flash()); // Passport初始化 app.use(passport.initialize()); app.use(passport.session());
原理说明
failureRedirect: '/login'让Passport在认证失败时跳转回登录页,替代默认的401响应req.flash存储的错误信息会随会话传递到登录页,在EJS模板中读取并展示- 统一的错误处理逻辑覆盖了用户不存在、密码错误、服务器异常等所有失败场景
内容的提问来源于stack exchange,提问作者Popa Alexandru Ionut
相关产品推荐
相关产品推荐

