已解决:在节点js中解密电子邮件激活令牌后,我的代码无法加密保存在mongoDB中的密码,我该如何解决?

Solved: my code is unable to encrypt the password to save in mongoDB after email activation token is decrypted in node js, how can i solve it?

我正在尝试通过 MERN 实施 jwt 身份验证,在 nodejs 中,我使用电子邮件激活 link 将用户电子邮件和密码保存在 mongodb 中。这是我注册用户和激活用户的工作示例。我正在使用 sendgrid 发送电子邮件。

//for email verification test

signup = async (req, res) => {
  const { username, email, password, passwordCheck, displayName } = req.body;
    //validate
    if (!username || !email || !password || !passwordCheck)
      return res.status(400).json({
        msg: "not all fields have been entered.",
      });
    if (password.length < 8)
      return res.status(400).json({
        msg: "The password needs to be at least 8 characters long.",
      });
    if (password !== passwordCheck)
      return res
        .status(400)
        .json({ msg: "Enter the same password twice for verification." });
    const existingUser = await User.findOne({ email: email });
    if (existingUser)
      return res
        .status(400)
        .json({ msg: "An account with this email already exists." });
    const existingUserName = await User.findOne({ username: username });
    if (existingUserName)
      return res
        .status(400)
        .json({ msg: "An account with this username already exists." });
    if (!displayName) displayName = email;

    const token = jwt.sign(
      { username, email, password, passwordCheck, displayName },
      process.env.JWT_SECRET,{expiresIn:'1000m'}
    );
    const msg = {
      to: email, //receiver's email
      from: "no-reply@test.com", // Change to your verified sender
      subject: `Email verification link ${displayName}`,
      text: "testing from local",
      html: `<h2>Hi ${displayName}</h2> <br/>sends a message for verification test: http://localhost:3000/authentication/activate/${token}</p> <br/><p>Have a nice day</p>`,
    };
    sgMail.setApiKey(process.env.SENDGRID_SECRET_API);
    sgMail
      .send(msg)
      .then((result) => {
        res.json({ message: "Email activation link has been sent" });
      })
      .catch((error) => {
        console.error(error);
        res.status(500).json("Error");
      });

}
router.post("/register", signup);

userActivation = (req, res)=>{
    const { token } = req.body;
  if(token){
    jwt.verify(token, process.env.JWT_SECRET,function(err,decodeToken){
      if(err){
        return res.status(400).json({error:'Incorrect or expired link.'})
      }
    const { username, email, password, passwordCheck, displayName }=decodeToken;
    
    const newUser = new User({
      username,
        email,
      password,
      displayName,
    });
    newUser.save((err,success)=>{
      if(err){
        console.log("Error in signup with account activation",err)
        return res.status(400).json({error:"Error activating account"})
      }
      res.json({
        message:"signup Success!!"
      })
    });
     
  
    } );
  } else{
    return  res.json({error:"Something went wrong"})
  } 

}

router.post("/email-activate",userActivation)

在使用 postman 保存用户和激活密钥时,在 mongodb 中密码以纯文本形式保存。由于安全问题,我不希望它以纯文本形式保存。我希望它以加密方式保存并尝试使用以下代码:

userActivation = async (req, res) => {
    const { token } = req.body;
    if (token) {
        jwt.verify(token, process.env.JWT_SECRET, function (err, decodeToken) {
            if (err) {
                return res.status(400).json({ error: "Incorrect or expired link." });
            }
            const { username, email, password, displayName } = decodeToken;
            console.log(password)
            User.findOne({ email }).exec((err, user) => {
                if (user) {
                    return res.status(400).json({ error: "Username with this email exists." })
                }
                const salt = bcrypt.genSalt();
                bcrypt.hash(password, salt,  (err, passwordHash)=>{
                    const newUser = new User({
                        username,
                        email,
                        password: passwordHash,
                        displayName,
                    });
                     console.log(password) 
                    console.log(passwordHash)
                    newUser.save((err, success) => {
                        if (err) {
                            console.log("Error in signup with account activation", err);
                            return res.status(400).json({ error: "Error activating account" });
                        }
                        res.json({
                            message: "signup Success!!",
                        });
                    })
                })
            })
        })
    }
}   

当我启动我的服务器并尝试通过 postman 使用激活密钥登录时,它向我发送了一个激活 link。当我尝试通过激活中的 postman 发送 post 请求时 link,postman 显示 404 状态“错误激活帐户”并且节点索引显示以下错误:

        The server has started on port: 5000
    MongoDB connected
    **the real password is showing undecoded**
**the real password is showing undecoded**
    undefined
    Error in signup with account activation Error: user validation failed: password: Path `password` is required.
        at ValidationError.inspect (C:\Myfiles\Reactjs\Projects\test-projects\node_modules\mongoose\lib\error\validation.js:47:26) 
        at formatValue (internal/util/inspect.js:731:31)
        at inspect (internal/util/inspect.js:295:10)
        at formatWithOptionsInternal (internal/util/inspect.js:1958:40)
        at formatWithOptions (internal/util/inspect.js:1842:10)
        at Object.value (internal/console/constructor.js:306:14)
        at Object.log (internal/console/constructor.js:341:61)
        at C:\Myfiles\Reactjs\Projects\test-projects\routes\userRouter.js:243:37
        at C:\Myfiles\Reactjs\Projects\test-projects\node_modules\mongoose\lib\model.js:4863:16
        at C:\Myfiles\Reactjs\Projects\test-projects\node_modules\mongoose\lib\helpers\promiseOrCallback.js:16:11
        at C:\Myfiles\Reactjs\Projects\test-projects\node_modules\mongoose\lib\model.js:4886:21
        at C:\Myfiles\Reactjs\Projects\test-projects\node_modules\mongoose\lib\model.js:500:16
        at C:\Myfiles\Reactjs\Projects\test-projects\node_modules\kareem\index.js:247:48
        at next (C:\Myfiles\Reactjs\Projects\test-projects\node_modules\kareem\index.js:168:27)
        at next (C:\Myfiles\Reactjs\Projects\test-projects\node_modules\kareem\index.js:170:9)
        at Kareem.execPost (C:\Myfiles\Reactjs\Projects\test-projects\node_modules\kareem\index.js:218:3) {
      errors: {
        password: ValidatorError: Path `password` is required.
            at validate (C:\Myfiles\Reactjs\Projects\test-projects\node_modules\mongoose\lib\schematype.js:1256:13)
            at C:\Myfiles\Reactjs\Projects\test-projects\node_modules\mongoose\lib\schematype.js:1239:7
            at Array.forEach (<anonymous>)
            at SchemaString.SchemaType.doValidate (C:\Myfiles\Reactjs\Projects\test-projects\node_modules\mongoose\lib\schematype.js:1184:14)
            at C:\Myfiles\Reactjs\Projects\test-projects\node_modules\mongoose\lib\document.js:2502:18
            at processTicksAndRejections (internal/process/task_queues.js:75:11) {
          properties: [Object],
          kind: 'required',
          path: 'password',
          value: undefined,
          reason: undefined,
          [Symbol(mongoose:validatorError)]: true
        }
      },
      _message: 'user validation failed'
    }

根据上面的尝试,代码无法加密密码,因此无法保存在mongodb中。我在对密码进行编码时做错了什么? 那么我该如何解决呢?

提前致谢

const passwordHash =  bcrypt.hash(password, salt);
Here bcrypt.hash returning promise either your can use async/await or use .then().



            userActivation = async (req, res) => {
        const { token } = req.body;
        if (token) {
            jwt.verify(token, process.env.JWT_SECRET, function (err, decodeToken) {
                if (err) {
                    return res.status(400).json({ error: "Incorrect or expired link." });
                }
                const { username, email, password, displayName } = decodeToken;
                console.log(password);
                User.findOne({ email }).exec((err, user) => {
                    if (user) {
                        return res.status(400).json({ error: "Username with this email exists." })
                    }
//Use genSaltSync when you donot want to use await or your can use await bcrypt.genSalt()
                    const salt = bcrypt.genSaltSync(10);
                    bcrypt.hash(password, salt,  (err, passwordHash)=>{
                        const newUser = new User({
                            username,
                            email,
                            password: passwordHash,
                            displayName,
                        });
                        newUser.save((err, success) => {
                            if (err) {
                                console.log("Error in signup with account activation", err);
                                return res.status(400).json({ error: "Error activating account" });
                            }
                            res.json({
                                message: "signup Success!!",
                            });
                        })
                    })
                })
            })
        }
    }

Try this code once just put await before bcrypt and made function async.