You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何修改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

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.18 12:57:32