リセットパスワード機能を実装する方法


あなたはnodejsとPostgreSQLとサーバー上でリセットパスワード機能を実装する方法を疑問に思ったことがありますか?
私はノードとmongodbでそれをする方法に関する多くの記事とチュートリアルを見つけました.
最初に、私たちは電子メールサービスを見つける必要があります、私は最初にnodemailerを試みました、そして、それは完全に私のローカル環境で働きます、しかし、生産で、私は私のGmailアカウントで若干のセキュリティ問題を得ていました.そういうわけで、私はsendgridで行くことに決めました.
クリエイトアSendGrid account , 電子メールAPI、統合ガイドに移動し、Web APIを選択し、ちょうどAPIキーを生成する指示に従ってください

依存関係のインストール
npm install --save @sendgrid/mail
npm install express bcryptjs jsonwebtoken knex
APIキーを作成しました.envファイルをキーを格納します.
どのように我々のユーザーテーブルが見えるか見ましょう
私はデータベースと対話するためにKenexライブラリを使用しています
table.increments();
table.string("email", 128).unique().notNullable();
table.string("password", 128).notNullable();
table.string("resetLink", 255);
ご覧の通り定義します"resetLink" オプションです.
さあ、ルートを作ろう
const express = require('express');
const bcrypt = require('bcryptjs');
const jwt = require('jsonwebtoken');
const sgMail = require('@sendgrid/mail');

const route = express.Router();
// bring env variables into file
const sendGridKey = process.env.SENDGRID_KEY;
const resetSecret = process.env.RESET_SECRET;

route.patch('/forgot-password', async (req, res) => {
  const { email } = req.body;

  try {
    // look for email in database
    const [user] = await filterBy({ email });
    // if there is no user send back an error
    if(!user) {
      res.status(404).json({ error: "Invalid email" });
    } else {
      // otherwise we need to create a temporary token that expires in 10 mins
      const resetLink = jwt.sign({ user: user.email }, 
      resetSecret, { expiresIn: '10m' });
      // update resetLink property to be the temporary token and then send email
      await update(user.id, { resetLink });
      // we'll define this function below
      sendEmail(user, resetLink);
      res.status(200).json({ message: "Check your email"} );
    }
  } catch(error) {
    res.status(500).json({ message: error.message });
  }
}
新しい定義を定義しましょうPATCH 新しいパスワードを更新するルート

route.patch('/reset-password/:token', async (req, res) => {
  // Get the token from params
  const resetLink = req.params.token;
  const newPassword = req.body;

  // if there is a token we need to decoded and check for no errors
  if(resetLink) {
    jwt.verify(resetLink, resetPassword, (error, decodedToken) => {
         if(error) {
           res.status().json({ message: 'Incorrect token or expired' })
         }
    })
  }

  try {
    // find user by the temporary token we stored earlier
    const [user] = await filterBy({ resetLink });

    // if there is no user, send back an error
    if(!user) {
      res.status(400).json({ message: 'We could not find a match for this link' });
    }

    // otherwise we need to hash the new password  before saving it in the database
    const hashPassword = bcrypt.hashSync(newPassword.password, 8);
    newPassword.password = hashPassword;

    // update user credentials and remove the temporary link from database before saving
    const updatedCredentials = {
      password: newPassword.password,
      resetLink: null
    }

    await update(user.id, updatedCredentials);
    res.status(200).json({ message: 'Password updated' });
  } catch (error) {
    res.status(500).json({ message: error.message });
  }
})
この場合、データベースと対話するために使用している関数も定義しましょうfindBy() and update()
// I'm using knex to interact with the database here
// but all is doing is looking into 'users' table and filtering the data by the filter parameter
function filterBy(filter) {
  return db('users').where(filter);
}

// same here, looking into 'users' table by 'id' and then updating the values
function update(id, changes) {
  return db('users').where({ id }).update(changes);
}
定義しましょうsendEmail 機能
function sendEmail(user, token) {
  sgMail.setApiKey(sendGridKey);
  const msg = {
    to: user.email,
    from: "", // your email
    subject: "Reset password requested",
    html: `
     <a href="${clientURL}/reset-password/${token}">${token}</a>
   `
   // I'm only going to use an (a tag) to make this easier to
   // understand but feel free to add any email templates 
   // in the `html` property
  };

  sgMail.send(msg)
    .then(() => {
      console.log("Email sent");
  }).catch((error) => {
      console.error(error);
  })
}
今、私たちがそれをテストするために郵便配達人を使うつもりであるルートを作成したので、我々はAを作る必要がありますPATCH リクエスト

すべてがOKであるならば、あなたは200のステータスを得なければなりません

Postman貼り付けのトークンurl/auth/reset-password/:token下記の例を参照

あなたは200のステータスコードを取得する必要がありますPassword update メッセージ
完全な例コードで私のreposのうちの1つへのリンクは、ここにありますrepo
私はあなたがこの助けを見つける願っています!あなたが質問をするならば、私にコメントで知らせさせてください.
私は同じ機能を追加する予定ですが、REDISを使用してデータベースの代わりにテンポラリトークンを保存します.