我正在构建一个Node.js应用程序,但在登录验证方面遇到了问题.我对bcryptjs使用的是Passport-local策略,但是当用户名在数据库中不存在时,它会正确地识别用户名,即使提供了错误的密码,它也会登录用户.

我可能犯了一个非常愚蠢的错误,但一些指点会很棒!

Passport.js:

const passport = require("passport");
const LocalStrategy = require("passport-local").Strategy;
const bcrypt = require("bcryptjs");
const connection = require("./database");
const User = connection.models.User;

const verifyUser = (username, password, done) => {
  User.findOne({ username: username }).then((user) => {
    if (user == null) {
      return done(null, false, { message: "No user with this username" });
    }

    try {
      if (bcrypt.compare(password, user.password)) {
        return done(null, user);
      } else {
        return done(null, false, { message: "Incorrect password" });
      }
    } catch (err) {
      return done(err);
    }
  });
};

passport.use(
  new LocalStrategy(
    { usernameField: "username", passwordField: "password" },
    verifyUser
  )
);

passport.serializeUser((user, done) => {
  done(null, user.id);
});

passport.deserializeUser((userId, done) => {
  User.findById(userId)
    .then((user) => {
      done(null, user);
    })
    .catch((err) => done(err));
});

注册和登录POST请求(auth.js):

router.post("/register", async (req, res, next) => {
  const { error } = registerValidation(req.body);

  if (error) {
    return res.status(400).send({ message: error["details"][0]["message"] }); // Message to be tidied but works
  }

  const userExists_1 = await User.findOne({ username: req.body.username });
  if (userExists_1) {
    return res
      .status(400)
      .send({ message: "An account with the same username already exists" }); // Message to be tidied but works
  }

  const userExists_2 = await User.findOne({ email: req.body.email });
  if (userExists_2) {
    return res.status(400).send({
      message: "An account is already registered to this email address", // Message to be tidied but works
    });
  }

  try {
    const hashedPassword = await bcrypt.hash(req.body.password, 10);
    const user = new User({
      username: req.body.username,
      email: req.body.email,
      password: hashedPassword,
    });

    user.save().then((user) => {
      console.log(user);
    });

    res.redirect("./login");
  } catch {
    res.redirect("./register");
  }
});

// ----------------------------------------------------

router.post(
  "/login",
  passport.authenticate("local", {
    failureRedirect: "/login",
    successRedirect: "/home",
    failureFlash: true,
  })
);

推荐答案

看起来comparebcrypt方法使用了回调或promise .

Cf documentation:

// As of bcryptjs 2.4.0, compare returns a promise if callback is omitted:
bcrypt.compare("B4c0/\/", hash).then((res) => {
    // res === true
});

请try 将您的db回调函数更新为asyncawait以响应bcrypt

User.findOne({ username: username }).then(async (user) => {
  // ..

  if (await bcrypt.compare(password, user.password)) {
  // ..

  }
}

Node.js相关问答推荐

在导入时未找到Pupeteer-PAGE-Proxy包

@nuxtjs/站点 map 错误提示:找不到包';NitroPack';

Mongoose更新在^8.0.3版中,许多似乎不能按预期工作

Mongoose抱怨说,整数是数字,而不是整数

JEST模拟由http服务器控制器导入的ES模块

将图像添加到多个产品的条带 checkout 会话中

Mongodb - 在数组数组中查找()

DynamoDB 分页数据检索

使用pm2启动服务器

在对象数组中的数组中嵌套 $lookup - Mongodb

登录用户并获取他们的个人资料

npm chokidar 触发事件两次

当我使用 uuid 代码意外崩溃,然后工作正常?

如何将子集合添加到 Firestore 中的文档?

Node应用程序中相同npm包的两个版本

Express.js中的bodyParser.urlencoded({extended: true }))和bodyParser.json()是什么意思?

Heroku + Node:找不到模块错误

我应该如何在 webpack 中使用时刻时区?

响应分块时获取整个响应正文?

Express js 阻止 GET /favicon.ico