導入
ウェブサイトのパスワードを保護することは、どんな開発者にも必要なスキルです。 JavaScript
は、JavaScript
のBcryptJS
モジュールが提供するハッシュアルゴリズムを使用して、パスワードやその他の機密データの安全な保存と処理を保証するオプションを提供します。
このチュートリアルでは、BcryptJS
とハッシュ化について学び、パスワードを生の文字列ではなくハッシュとしてデータベースに保存し、認証のためにそれらを取得する基本的なエクスプレスサーバーを設定します。
前提条件
このチュートリアルを続けるには、以下のセットアップが必要です。
-
コンピュータに安定したバージョンのNode.jsをインストールしておく必要があります。バージョンは12.x以上である必要があります。最新のNode.jsバージョンをインストールするために、こちらのDigitalOceanのチュートリアルを使用できます。
-
_コンピュータにExpress JSをインストールしておく必要があります。Expressサーバーのセットアップ方法については、こちらのガイドを使用することができます。
-
最後に、このチュートリアルを完了するためには、MongoDB CommunityまたはAtlasデータベースが必要です。MongoDBのインストール方法については、次のいずれかのDigitalOceanガイドを使用してインストールできます_ MongoDBのインストール方法。
BcryptJSを使用する理由はなぜですか?
Bcryptは、パスワードのハッシュを作成してデータの漏洩の場合に保管するためのハッシュ化アルゴリズムです。この高度なハッシュ化アルゴリズムは、ソルトを使用しており、ブルートフォース攻撃などの攻撃に対して耐性があります。
BcryptJSは、Bcryptハッシュアルゴリズム
のJavaScript実装であり、複雑なハッシュ関数に関与することなくハッシュ暗号化を使用することができます。BcryptJSがパスワードセキュリティにおいて優れた選択肢となる理由の一部は以下の通りです:
-
セキュリティ – BcryptJSはBcryptアルゴリズムを実装しており、遅いアルゴリズム(ハッシュにおいては良いもの)であり、強力な計算能力が必要です。これにより、攻撃者がパスワードハッシュをクラックすることは困難になり、データ侵害の場合でもパスワードの安全性を保証します。
-
ソルティング – BcryptJSはパスワードのランダムソルトの生成を処理し、ストレージのセキュリティを確保します(ハッシュとソルトについては次のセクションで詳しく学びます)。ソルトは比較的弱いパスワードのハッシュを複雑化し、解読を困難にします。
-
使いやすさ – BcryptJSはJavaScript開発者に対して、ハッシュに対する深い理解を必要とせずにパスワードを暗号化するためのツールを提供します。
次のステップでは、ハッシュとソルトについて簡単に説明します。
ハッシングの仕組みは?
これらの概念をプロジェクトで使用する前に、ハッシングとソルティングの仕組みを理解する必要があります。
ハッシング
ハッシングとは、単純な文字列や平文をランダムな文字列(暗号化)に変換することです。これにより、機密データの安全な保存や送信が可能になります。ハッシングには以下の主要なステップが含まれます:
データ入力 – 最初に、バイナリ、文字、10進数などの任意のタイプのデータがプレーンテキストまたは文字列として保存されます。
ハッシュ関数 – ハッシュ関数は、データから入力を受け取り、文字列またはハッシュコードのセットに変換する数学的アルゴリズムです。ハッシュ関数は決定論的(同じ入力に対して同じ出力を生成する)であり、ワンウェイ関数です(つまり、ハッシュ関数の出力を入力データに戻すことはほぼ不可能です)。
衝突耐性 – これは、ハッシュ関数が衝突耐性の考えを念頭に置いて作成されることを意味します。つまり、2つの異なる入力は同じ出力(ハッシュコード)を持つことはありません。
認証 – ハッシュ関数は決定論的であり、同じ入力に対しては常に同じハッシュを生成します。したがって、パスワードをハッシュとして保存した場合、一般的な考え方は、認証するパスワードがデータベースに保存されているハッシュと一致する場合、パスワードが正しいということです。
ソルティング
ハッシュは何十年も前から存在しており、さまざまなハッシュアルゴリズムに基づいたデータ文字列とそれに対応するハッシュを含む数十億のデータエントリを含むレインボーテーブルなどの開発が行われてきました。
さて、ウェブサイトでアカウントを作成するユーザーが弱いパスワードを作成する状況を考えてみましょう。そのため、データの漏洩が発生した場合、攻撃者はユーザーのハッシュを検索し、弱いパスワードを持つユーザーアカウントのハッシュと一致するものを見つけることができます。これは、高セキュリティのアプリケーションでは壊滅的な結果となるでしょう。このような事態を防ぐために、ソルトが使用されます。
ソルトは、パスワードのハッシュをデータベースに保存する前に、ランダムな文字列をハッシュに追加することで、ハッシュに対して追加のセキュリティレイヤーを提供します。したがって、データが漏洩した場合でも、攻撃者がソルトを含むハッシュを解読することは困難になります。以下に例を示します。
明らかにわかるように、ハッシュの決定論的な性質により、ソルトで保存されたパスワードは解読することが困難です。したがって、例えば、攻撃者がこのハッシュ+パスワードの文字列をレインボーテーブルで検索しても、実際のパスワードの文字列ではなく、完全に異なるものが得られます。
さて、BcryptJSを使ってパスワードを業界標準の方法で安全に保護する準備が整いました。
BcryptJSおよび他の必要なモジュールのインストール
ハッシュ化とソルトについて知ったので、あとはコンピュータを手に入れてコードを書くだけです。プロジェクトの構造は以下のようになります:

まず、次の手順でnpmプロジェクトを作成します:
-
フォルダを開き、
app.js
というファイルを作成します。 -
このフォルダでターミナルウィンドウを開き、次のコマンドを入力します。
その後、入力を求められますが、何も入力せずにEnterキーを押すことができます。
- 次に、
auth.js
、
db.js
- 、
User.js
- という3つのファイルを作成します。
- 同じターミナルウィンドウで、次のコマンドを入力して必要なパッケージをインストールします。
このチュートリアルでは、完全なプロジェクト環境が設定されました。次のステップでは、BcryptJSを使用してパスワードを安全に保存および認証するためのサーバーの作成方法を学びます。
Express JSを使用したサーバーのセットアップ
プロジェクトの構造が設定されたので、ハッシュとしてパスワードを保存し、認証するためにbcrytjs
を使用するサーバーを作成できます。次の適切な手順でサーバーを作成します。
ステップ1 – MongoDBデータベースへの接続の作成
mongoDB
に接続するために、コミュニティ版を使用します。プロジェクトを整理するために、接続の設定コードをdb.js
ファイルに保存します。
ここでは、mongoose
パッケージをインポートして、JavaScriptをMongoDB
に接続するAPIを提供します。また、この場合、接続URIはローカルインストールのmongoDB用であり、クラウドデータベース(Atlasなど)を使用している場合は、URIを特定のデータベースのURIに変更するだけです。
情報
URIは、リソースの名前と識別子、およびインターネット上の場所を識別することができるサーバーのURLと似ています。一方、URLはURIのサブセットであり、後者のみを実行することができます。
connectToMongo
関数は、mongoose.connect
がJavaScriptのプロミスを返すため、非同期関数です。この関数は正常に実行された場合、接続を返します。それ以外の場合はエラーを返します。
最後に、db.js
モジュールがインポートされるたびに、この関数をエクスポートするためにmodule.exports
を使用します。
ステップ2 – ユーザースキーマの作成
MongoDBデータベースでユーザーを作成または認証するために、基本的なスキーマが必要です。スキーマが何であるかわからない場合は、この優れたDOガイドを使用してMongoDBでスキーマを理解して作成することができます。スキーマでは、email
とpassword
の2つのフィールドのみを使用します。
次のコードをUser.js
モジュールに使用してください。
このスキーマには、email
とpassword
の2つのフィールドがあります。どちらも必須フィールドであり、文字列のデータ型です。また、email
はユニークフィールドであり、つまりこのサーバー上でアカウントを持つために1つのメールアドレスしか使用できません。
最後に、users
という名前のモデルをエクスポートします。モデルはデータベースのスキーマを表します。スキーマはモデルを定義するためのルールと考えることができ、モデルはMongoDB
データベース内のコレクションとして保存されます。
スキーマをモデルに変換するには、mongoose
ライブラリのmodel()関数を使用します。
ステップ3 – app.jsでサーバーをセットアップする
前の手順に従った後、モデルとMongoDB
データベースへの接続用のモジュールを正常に作成しました。次に、サーバーのセットアップ方法を学びます。以下のコードをapp.js
ファイルに使用してください。
ここでは、express
とdb.js
モジュールをインポートしてMongoDBに接続します。次に、JSONレスポンスを処理するためにexpress.json()
ミドルウェアを使用します。ルートは別のモジュール(auth.js
)で作成され、コードをきれいかつ整理された状態に保ちます。最後に、サーバーがローカルホストのポート3300
でリッスンするエンドポイントを作成します(任意のポートを使用できます)。
パスワードの暗号化とMongoDBデータベースへの保存
この時点では、サーバーはほぼ準備ができており、今度はサーバーのためのエンドポイントを作成します。2つのエンドポイント、signup
とlogin
を作成します。signupエンドポイントでは、新しいユーザーからメールアドレスとパスワードを取得し、BcryptJS
を使用してパスワードを暗号化して保存します。
auth.js
ファイルに以下のコードを入力してください:
必要なインポートを行い、expressルーターを設定して/signup
エンドポイントを作成します。アプリケーション内でURLに資格情報が表示されないように、POST
メソッドを使用しています。その後、scripts
パッケージのgenSalt
関数を使用してSaltを作成します。genSalt()
関数に渡されるパラメータは、Saltの文字数です。次に、BcryptJSのhash()
関数を使用し、ハッシュコードに変換する必要なパラメータであるパスワード文字列と、オプションの引数であるSalt文字列を指定します。そして、password
とsalt
の両方を含むハッシュが返されます。
その後、mongoose
モジュールのcreate()関数を使用して、usersモデルのルールで定義されたデータベース内にドキュメントを作成します。この関数は、メールとパスワードを含むJavascript
オブジェクトを受け取りますが、生の文字列ではなく、データベースに保存するためにsecPass(パスワードのハッシュ
+ ソルト
)を渡します。これにより、生の文字列ではなく、ハッシュとソルトを組み合わせてパスワードを安全にデータベースに保存することができます。最終的に、ユーザーモデルを含むJSON
レスポンスを返します(このレスポンスの送信方法は開発フェーズ
のみに使用されます。本番環境では、認証トークンまたは他の方法に置き換える必要があります)。
このエンドポイントをテストするには、まずサーバーを実行する必要があります。ターミナルに以下のコマンドを入力してください。
このコマンドにより、サーバーがlocalhostのポート3300
(または指定したポート)で実行されます。その後、以下のボディを持つURL http://localhost:3300/auth/signup
へHTTP
リクエストを送信することができます:
これにより、以下の出力/レスポンスが生成されます:
注意:パスワードのハッシュとIDは常に一意であるため、同じではありません。
次のセクションでは、保存されたパスワードのハッシュにアクセスし、ログイン/認証時に提供されたパスワードを認証する方法について説明します。
暗号化されたパスワードへのアクセスと認証の使用
これまで、BcryptJS
、ハッシング
、ソルト
、およびハッシュとして格納されたパスワードを持つ新しいユーザーを作成するexpressサーバー
の作成方法について学びました。次に、アプリケーションにログインしようとするユーザーのパスワードを使用してユーザーを認証する方法について学びます。
認証方法を追加するには、/signup
ルートの後に次のルートをauth.js
に追加します:
ここでは、既存のユーザーのログイン認証を行うために/auth/login
サブパスを使用します。 /auth/signup
エンドポイントと同様に、これはBcryptJSがプロミスを返すため、非同期の待機関数になります。
まず、MongooseライブラリのfindOne
関数を使用して、指定された検索クエリに基づいてコレクション内のドキュメントを検索するために使用します。この場合、私たちはメールに基づいてユーザーを検索しています。指定されたメールを持つユーザーが存在しない場合、これは無効な資格情報のためのステータスコード400でレスポンスを送信します。(ログイン時にどのパラメータが間違っているかを提供することは良い慣行ではありません。攻撃者はその情報を使用して既存のアカウントを見つけることができます)。
提供されたメールアドレスのユーザーが存在する場合、プログラムはパスワードの比較に移動します。そのために、BcryptJS
はcompare()
メソッドを提供しています。このメソッドは、最初の引数として生の文字列を、2番目の引数としてhash
(salt
ありまたはなし)を取ります。そして、パスワードがハッシュと一致する場合はtrue
、一致しない場合はfalse
を返します。その後、if文を使用して簡単なチェックを追加し、比較に基づいて成功またはエラーを返すことができます。
最後に、express router
をmodule.exportsを使用してapp.js
の起点でエクスポートし、ルートに使用します。
このルートをテストするために、以下のようなボディを持つURL http://localhost:3300/auth/login
に別のHTTP
レスポンスを送信することができます:
このリクエストには以下のようなレスポンスが返されます:
最終的に、auth.js
は以下のようになります:
結論
このチュートリアルでは、BcryptJSを使用してデータベースのパスワードを安全に保存しアクセスする方法を説明しました。以下のような方法でさらに進めることができます:
-
ユーザーの資格情報の取得、ユーザーの資格情報の更新など、他のタスクのためのさらなるルートの実装
-
レスポンスとして送信するために、認証トークンを実装するなど。
これにより、パスワードを安全に扱うための旅が始まります。常に異なる技術や技法でより高いセキュリティを追加することができ、より安全かつ堅牢なアプリケーションを作成することができます。