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

如何将Passport.js登录验证的服务端错误传递至客户端?

Passport.js 登录错误提示不显示问题排查与解决

我用Passport.js编写了登录相关代码,成功登录后的successRedirect功能正常,但输入错误密码时没有任何提示,不清楚如何将服务端的验证错误展示到客户端。相关代码如下:

passport-config.js(LocalStrategy初始化代码)

const LocalStratigy = require('passport-local').Strategy
const bcrypt = require('bcrypt')

const initialize = (passport, getUserByEmail, getUserById) => {
  const authenticateUser = async (email, password, done) => {
    const user = getUserByEmail(email) // 后续会实现这个函数,不用在意
    if (user == null) {
      return done(null, false, {
        messege: "No user with that email"
      }) // done是参数中传入的回调函数
    }
    try {
      if (await bcrypt.compare(password, user.password)) {
        return done(null, user)
      } else {
        return done(null, false, {
          messege: "wrrong password "
        })
      }
    } catch (error) {
      return done(error)
    }
  }
  passport.use(new LocalStratigy({
    usernameField: 'email'
  }, authenticateUser))
  passport.serializeUser((user, done) => done(null, user.id))
  passport.deserializeUser((id, done) => {
    return done(null, getUserById(id))
  })
}

module.exports = initialize

serveur.js(服务端路由代码)

app.post('/signin', passport.authenticate('local', {
  successRedirect: '/',
  failureRedirect: '/signin',
  failureFlash: true
}))

signin.html(客户端页面,其中JavaScript代码无法正常工作)

<!DOCTYPE html>
<html lang="en">
<head>
  <meta charset="UTF-8">
  <meta http-equiv="X-UA-Compatible" content="IE=edge">
  <meta name="viewport" content="width=device-width, initial-scale=1.0">
  <title>Document</title>
  <link rel="stylesheet" href="signup.css">
</head>
<body>
  <div id="messeges">
  </div>
  <form action="signin" method="post">
    <div class="box">
      <div class="from">
        <h2>Sign in</h2>
        <div class="inputbox">
          <input type="email" name="email" id="email" required="required">
          <span>Email Adress</span>
          <i></i>
        </div>
        <div class="inputbox">
          <input type="password" id="password" name="password" required="required">
          <span>Password</span>
          <i></i>
        </div>
        <div class="links">
          <a href="./signup.html">Forgot Password</a>
          <a href="./signup.html">sign up</a>
        </div>
        <input type="submit" value="Login">
      </div>
    </div>
  </form>
  <script>
    const messege = document.getElementById('messeges')
    if (messages.error) {
      messege.innerHTML = "<h1>messages.error</h1>"
    }
  </script>
</body>
</html>

问题原因与解决步骤

1. 服务端缺失Flash消息中间件配置

你在passport.authenticate中启用了failureFlash: true,但未配置express-flash中间件,导致服务端无法将错误消息传递到客户端。

解决:

  • 安装依赖包:
npm install express-flash express-session
  • 在serveur.js中添加中间件配置(需放在Passport初始化之前):
const flash = require('express-flash')
const session = require('express-session')

// 配置session
app.use(session({
  secret: '你的随机密钥', // 替换为自定义密钥
  resave: false,
  saveUninitialized: false
}))

// 启用Flash消息
app.use(flash())

// 初始化Passport(确保在session和flash配置之后)
const initializePassport = require('./passport-config')
initializePassport(passport, getUserByEmail, getUserById)

2. 客户端未正确获取服务端错误消息

当前HTML中的JavaScript存在变量名拼写错误,且未从服务端获取错误数据:

  • messege与messages拼写不一致
  • 直接访问未定义的messages.error变量

以下提供两种解决方案:

方案一:改用模板引擎(推荐)

将静态HTML改为模板文件(以EJS为例),直接在服务端渲染时传递错误消息:

  • 安装EJS:npm install ejs
  • 配置模板引擎:
app.set('view engine', 'ejs')
  • 修改登录路由,手动处理认证结果并传递消息:
// 替换原POST路由
app.post('/signin', (req, res, next) => {
  passport.authenticate('local', (err, user, info) => {
    if (err) return next(err)
    if (!user) {
      req.flash('error', info.messege)
      return res.redirect('/signin')
    }
    req.logIn(user, (err) => {
      if (err) return next(err)
      return res.redirect('/')
    })
  })(req, res, next)
})

// GET路由渲染登录页并传递错误消息
app.get('/signin', (req, res) => {
  res.render('signin', { error: req.flash('error')[0] })
})
  • 修改signin.ejs内容:
<!DOCTYPE html>
<html lang="en">
<head>
  <meta charset="UTF-8">
  <meta http-equiv="X-UA-Compatible" content="IE=edge">
  <meta name="viewport" content="width=device-width, initial-scale=1.0">
  <title>Document</title>
  <link rel="stylesheet" href="signup.css">
</head>
<body>
  <% if (error) { %>
    <div id="messeges">
      <h1><%= error %></h1>
    </div>
  <% } %>
  <!-- 表单内容保持不变 -->
  <form action="/signin" method="post">
    <div class="box">
      <div class="from">
        <h2>Sign in</h2>
        <div class="inputbox">
          <input type="email" name="email" id="email" required="required">
          <span>Email Adress</span>
          <i></i>
        </div>
        <div class="inputbox">
          <input type="password" id="password" name="password" required="required">
          <span>Password</span>
          <i></i>
        </div>
        <div class="links">
          <a href="./signup.html">Forgot Password</a>
          <a href="./signup.html">sign up</a>
        </div>
        <input type="submit" value="Login">
      </div>
    </div>
  </form>
</body>
</html>
方案二:静态HTML通过查询参数传递错误

若坚持使用静态HTML,可通过URL查询参数传递错误消息:

  • 修改服务端路由:
app.post('/signin', (req, res, next) => {
  passport.authenticate('local', (err, user, info) => {
    if (err) return next(err)
    if (!user) {
      const encodedError = encodeURIComponent(info.messege)
      return res.redirect(`/signin?error=${encodedError}`)
    }
    req.logIn(user, (err) => {
      if (err) return next(err)
      return res.redirect('/')
    })
  })(req, res, next)
})
  • 更新signin.html中的JavaScript:
<script>
  const messageDiv = document.getElementById('messeges')
  const urlParams = new URLSearchParams(window.location.search)
  const error = urlParams.get('error')
  if (error) {
    messageDiv.innerHTML = `<h1>${error}</h1>`
    // 清除查询参数,避免刷新页面重复显示错误
    window.history.replaceState({}, document.title, window.location.pathname)
  }
</script>

3. 代码拼写错误修正

  • LocalStratigy改为LocalStrategy(拼写错误)
  • messege统一改为message(避免拼写混乱)
  • wrrong password改为Wrong password(拼写错误)

修正后的passport-config.js关键代码:

const LocalStrategy = require('passport-local').Strategy
// ...
if (user == null) {
  return done(null, false, {
    message: "No user with that email"
  })
}
// ...
} else {
  return done(null, false, {
    message: "Wrong password"
  })
}

内容的提问来源于stack exchange,提问作者dhia mlayah

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.28 03:05:33