通过电子邮件重置密码

Resetting password via email

抱歉这么久 post,我正在尝试通过电子邮件重置密码,直到现在我设法将重置 link 发送到电子邮件,现在我在后台尝试了这个:

userRouter.get('/reset', expressAsyncHandler(async (req, res) => {
  const user = await User.findOne({
    where: {
      resetPasswordToken: req.query.resetPasswordToken,
      resetPasswordExpires: {
        $gt: Date.now(),
      },
    },
  });
  if (user) {
    console.log('token matched')
    res.status(200).send({
      message: 'password reset link ok'
    })
  } else {
    console.log('password reset link is invalid or has expired');
    res.json('password reset link is invalid or has expired');
  }
})
);

在忘记密码时,我做了类似这样的事情来更新两个字段:

user.update({
        resetPasswordToken: token,
        resetPasswordExpires: Date.now() + 360000,
      });

我的用户模型是:

    name: { type: String, required: true },
    email: { type: String, required: true, unique: true },
    password: { type: String, required: true },
    isAdmin: { type: Boolean, default: false, required: true }

当我尝试使用 where 子句检查 resetPasswordToken 是否返回我的所有用户时,这是错误的。我在想我需要在模型中声明 resetPasswordToken 和 resetPasswordExpires 以使其两项工作?还是足够了?另一个问题是,我必须将什么发送到前端才能正常工作?

在 react-redux 中,我有以下功能,但我 100% 发送了错误的数据:

export const checktoken = (email) => async (dispatch) => {
  dispatch({ type: USER_RESET_PASSWORD_REQUEST, payload: { email } });
  try {
    const { data } = await Axios.get('/api/users/reset');
    dispatch({ type: USER_RESET_PASSWORD_SUCCESS, payload: data });;
    localStorage.setItem('userInfo', JSON.stringify(data));
  } catch (error) {
    dispatch({
      type: USER_RESET_PASSWORD_FAIL,
      payload:
        error.response && error.response.data.message
          ? error.response.data.message
          : error.message,
    });
  }
};

首先,您的模型没有 resetPasswordTokenresetPasswordExpires 字段。这意味着您的 update 将不起作用。我假设您使用的是 mongoose,并且 mongoose 不会更新模型中不存在的字段。

添加条目如下。

name: { type: String, required: true },
email: { type: String, required: true, unique: true },
password: { type: String, required: true },
isAdmin: { type: Boolean, default: false, required: true },
resetPasswordToken: { type: String },
resetPasswordExpires: { type: Number }

其次,您的查询有误。查询应该像...

  const user = await User.findOne({
      resetPasswordToken: req.query.resetPasswordToken,
      resetPasswordExpires: {
        $gt: Date.now(), 
      },
  });

注意:经常检查您的数据库,看看您的 update 条目是否确实更新了。

前端

验证用户 + 令牌存在后,您可以 res.status(200).send() 到您的网络应用程序。

在您的网络应用程序中,您将请求用户输入新密码。用户输入新密码后,您会将新密码 AND 令牌(再次)发送到后端。

这一次,您需要在将密码更新到用户模型之前再次验证令牌。这将确保重置密码来自有效来源。

您可能希望在更新密码后从文档中删除 resetPasswordToken 和 resetPasswordExpires,因为不再需要它。