LoginSignup
7
5

More than 3 years have passed since last update.

node.js(express)でパスワードのハッシュ化 〜bcryptモジュールの使い方〜

Posted at

bcryptとは

password$2b$10$7f9myKwdo9BDUOkybKpQoOSMeEX90aRRFfOdj.c3dG6RIjZxZ/a4mみたいな感じにぐっちゃぐちゃにしてくれるnpmモジュール

使い方

まずはrequireで読み込み

const bcrypt = require('bcrypt')

ハッシュ化

const hashed = bcrypt.hash(req.body.password, 10)
//bcrypt.hash(ハッシュ化したいpassword, ストレッチング回数)
//ストレッチング回数 =ハッシュ化の回数で、2のn乗のnのことで4~31を指定できる

照合

const compared = bcrypt.compare(req.body.password, docs.password)
//bcrypt.compare(ハッシュ化前のpassword, ハッシュ化後のpassword)

ポイント

  • bcrypt.hashは時間がかかる為、非同期処理としてコントロールする必要。async awaitをつける
  • hash後にhash化したパスワードをデータベース等に保存する処理を書くことが多いと思いますが、その場合async awaitをつけないとハッシュ化が終わる前に次の保存処理を実行してしまう為、passwordがみつかりませんよ!みたいなエラーが出る。
  • bcryptにはhashSyncというメソッドも用意されており、これを使ってもasync await同様の同期的な動きをとる。が、どこかで非推奨?と見た事があります。

使用例 

現在勉強のため制作しているTodoアプリでexpress, mongooseを使っていますので、そこで使ったユーザー登録とログイン処理での使用例を記載致します。

<新規ユーザー登録>
クライアントからのフォーム送信で受けた新規ユーザーのpasswordを、ハッシュ化しデータベースに登録

router.post('/register', async (req, res) => {
  const hashedPassword = await bcrypt.hash(req.body.password, 10)

  console.log(hashedPassword);
//hashedPasswordにpromiseが返ってくるためawaitで処理の完了を待つ
//試しにawaitを外すとPromise{pending}がlogされる
//pendingは「わたし待ってます」状態

  const userData = new User({
    username: req.body.username,
    password: hashedPassword
//ここでhashedPasswordのpromiseが解決している必要がある
//そのためbcrypt.hashにawaitをつけて10回hashされるのを待ってから次の処理に進むように制御する
  })

// --- 以下DB登録処理 --- 
    User.find({ username: userData.username }, (err, docs) => {
    if (docs.length) {
      res.send({
        msg: 'そのユーザー名は使えません'
      })
      return
    } else {
      User.insertMany(userData)
      .then(() => res.send({
        msg: '登録が完了しました!ログインしてください'
      }))
    }
  })
})

<ログインユーザーの照合>
クライアントからのフォーム送信で受けたユーザーネームとpasswordをデータベースと照合し、合致するデータを取り出す

router.post('/login', (req, res) => {
// ユーザー名でデータベース検索する処理のサンプル

 User.find({
    username: req.body.username,
  }, async (err, docs) => {

    if (!docs.length) {
      res.send({
        msg: 'ユーザー名 か パスワード が間違っています',
        isLogin: false
      })
      return
    }

// ここからハッシュ前のpasswordとDB内のハッシュ済のpasswordとの照合

    const compared = await bcrypt.compare(req.body.password, docs[0].password)
// bcrypt.compare(ユーザーが入力したpassword, DBから引っ張ってきたハッシュ化済のpassword)
// bcrypt.compareもPromiseが返してくるのでasync,awaitで制御を加える
// 照合が終わったら次の処理へ進むようになる

    console.log(compared)
// passwordがあってればtrue まちがっていればfalse


    if (!hassed) {
      res.send({
        msg: 'ユーザー名 か パスワード が間違っています',
        isLogin: false
      })
      return
    } else {
      res.send({
        msg: 'ログインできました',
        isLogin: true,
        username: req.body.username
      })
    }
  })
})

以上です。

7
5
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
7
5