0

Users.js 中的代码在以下代码段中出现错误:qrcode.toDataURL(secret.otpauth_url, (err, data_url) => {

我尝试添加 return 语句以确保我不会多次发送响应。我可以看到在线转换为图像时的 data_url 向我显示了一个 QR 码,但是当我使用 Postman 时我看不到它。

router.post(
  "/",
  [
    check("name", "Name is required")
      .not().isEmpty(),
    check("email", "Please include a valid email").isEmail(),
    check(
      "password",
      "Please enter a password with 6 or more characters"
    ).isLength({ min: 6 })
  ],
async (req, res) => {
    console.log("hi");
    console.log(JSON.stringify(req.body));
    const errors = validationResult(req);
    if (!errors.isEmpty()) {
      //  return res.status(400).json({ errors: errors.array() });
    }

    const {
      name,
      email,
      password,
      type_of_user,
      question1,
      answer1,
    question2,
    answer2
    } = req.body;

    try {
      let user = await User.findOne({ email }); // await User.findOne({ email });



      user = new User({
        name,
        email,
        avatar,
        password,
        type_of_user,
        question1,
        answer1,
        question2,
        answer2
      });

      const salt = await bcrypt.genSalt(10); //await

      user.password = await bcrypt.hash(password, salt); // await

      user
        .save()
        .then(result => {
          // MFAOptions & secret will generate a secret
          const MFAOptions = {
            issuer: "xyz",
            user: req.body.email,
            length: 64
          };
          const secret = speakEasy.generateSecret(MFAOptions);

          const token = jwt.sign(
            {
              name: user.name,
              email: user.email,
              twofactor: false
            },

            config.get("jwtSecret"), // chnaged from process env jwt
            {
              expiresIn: "1h"
            }
          );

          // update the user that is just created:
          user
            .update(
              { email: req.body.email },
              {
                $set: { twoFASecret: secret.base32 }
              }
            )
            .exec()
            .then(result => {
              console.log(result);
              qrcode.toDataURL(secret.otpauth_url, (err, data_url) => {
                console.log(data_url);
                res.status(200).json({
                  img: data_url,
                  token: token
                });
              });
              return;
            })
            //if anything wrong, throws an error
            .catch(err => {
              console.log(err);
              //  res.status(500).json({ error: err });
            });
        })
        // originaly this will end here, but now it should redirect to twoFA route,
        // if something wrong, shows an error
        .catch(err => {
          console.log(err);
          //  res.status(500).json({ error: err });
        });

      // user with an id, primise which returns an id

      const payload = {
        user: {
          id: user.id
        }
      };

      jwt.sign(
        payload,
        config.get("jwtSecret"),
        { expiresIn: 3600 }, 
        (err, token) => {
          if (err) throw err;
          res.json({ token });
        }
      );
      //  } //else end
    } catch (err) {
      console.error(err.message);
      res.status(500).send("Server error");
    }
  }
);



module.exports = router;
4

1 回答 1

0

我认为您在执行此行时遇到的问题,qrcode.toDataURL(secret.otpauth_url, (err, data_url) => { 此调用有回调,这意味着您将继续执行其余代码并发送响应,res.json然后在 qrcode 完成后,它执行将进入回调并发送另一个不允许的响应。你有多次执行,因为res.json你需要删除其中一个并重构你的代码我试图重构你的代码:

const validation = [check('name', 'Name is required').not().isEmpty(),
check('email', 'Please include a valid email').isEmail(),
check('password', 'Please enter a password with 6 or more characters').isLength({ min: 6 })]

const toDataURL = (otpauth_url) => new Promise((resolve, reject) => {
  qrcode.toDataURL(secret.otpauth_url, (err, data_url) => {
    if(err)reject(err)
    resolve(data_url)
      res.status(200).json({
      img: data_url,
      token,
    })
  })
});
const signJwt = (payload)=>new Promise((resolve,reject)=>{
 return  jwt.sign(
      payload,
      config.get('jwtSecret'),
      { expiresIn: 3600 },
      (err, token) => {
        if (err) reject(err)
        resolve(token)
      }
    )
})
const postRequest = async (req, res) => {
  const errors = validationResult(req)
  if (!errors.isEmpty()) {
    return res.status(400).json({ errors: errors.array() })
  }
  const { name, email, password, type_of_user, question1, answer1, question2, answer2, } = req.body

  try {
    let user = await User.findOne({ email })
    user = new User({
      name,
      email,
      avatar,
      password,
      type_of_user,
      question1,
      answer1,
      question2,
      answer2,
    })
    const salt = await bcrypt.genSalt(10) // await
    user.password = await bcrypt.hash(password, salt) // await
    await user.save()
    // MFAOptions & secret will generate a secret
    const MFAOptions = {
      issuer: 'xyz', user: req.body.email, length: 64,
    }
    const secret = speakEasy.generateSecret(MFAOptions)

    const token = jwt.sign(
      {
        name: user.name,
        email: user.email,
        twofactor: false,
      },
      config.get('jwtSecret'), { expiresIn: '1h', })

    // update the user that is just created:
    await user.update({ email: req.body.email },
      { $set: { twoFASecret: secret.base32 }, }).exec()
      const  data_url= await toDataURL(secret.otpauth_url)
      if(data_url)    return   res.status(200).json({
        img: data_url,
        token,
      })
    const payload = {
      user: {
        id: user.id,
      },
    }
  const  token= await signJwt(payload)
  return res.json({token})

  } catch (err) {
    console.error(err.message)
  return  res.status(500).send('Server error')
  }
}
router.post('/', validation, postRequest)


module.exports = router
于 2019-10-20T21:01:39.963 回答