こんにちは、2024年4月入社の高田です。
第1回目の記事で会員登録機能を紹介しました。
今回の記事では前回の記事の延長としてログイン/ログアウト機能について紹介します。
ログイン機能
ログイン機能の実装は今回始めて行いました。普段は意識せずに使っていますが、実装者の立場で改めて考えてみると、どのようにしてログイン機能が実現されているか不明でしたので今回一から調べました。色々なwebサイトを参考に実装し最終的に以下のようなステップで実装を行いました。
1. メールアドレス、パスワード入力必須チェック
2. メールアドレスでのデータベース照会
3. パスワード認証
4. 認証成功時の処理
簡単にではありますが、ここからは上記の各ステップについて順に説明していきます。
1. メールアドレス、パスワード入力必須チェック
ログイン画面でメールアドレス、パスワードを入力し、「ログイン」ボタンを押下すると認証処理が始まります。この際、すべての項目が入力されているか確認し、未入力の場合は以下の画像のようなエラーメッセージが表示されます。
このように必要な情報が揃わない場合、次のステップには進めません。
2. メールアドレスでのデータベース照会
メールアドレスとパスワードの入力必須チェックが完了すると、入力されたメールアドレスを基にデータベースを参照し、該当するユーザーを探します。データベースには登録済みのユーザー情報が保存されており、入力されたメールアドレスと一致するユーザーが見つかった場合、そのユーザーのハッシュ化(※1)されたパスワードを取得します。このパスワードを用いて、次のステップであるパスワード照合に進みます。
(※1)ハッシュ化とは?
ハッシュ化とは、ハッシュ関数によって文字列を置換して、元の文字を推測できなくすることです。ハッシュ関数を用いてsaltと呼ばれるランダムな値をハッシュする値に追加することで、同じパスワードでも異なるハッシュ値が生成されます。データベースに保存されているパスワードはハッシュ化して保存されています。
ハッシュ化の例:
・パスワード:
!X9v#4hT8@pQ7wZ&2024
・ハッシュ値:f3f32592e1483974c378f46b4ab91500199b83b168ec87ed76ebdd66efe83452
※ 上記のようにハッシュ化されたパスワードをデータベースに保存します。
ハッシュ化の特性と利点:
ハッシュ化は一方向の変換であり、一度ハッシュ化されたデータを元に戻すことは極めて困難です。この特性を利用し、データベースに保存するパスワードをハッシュ化しておくことで、万が一データベースが攻撃されても、パスワードを直接利用されるリスクを大幅に減らすことができます。
参考: PHP: パスワードのハッシュ – Manual
以上より、ハッシュ化はパスワードを管理するための重要なセキュリティ対策となります。
3. パスワード認証
パスワード認証では、データベースに保存されているハッシュ化されたパスワードと、ユーザーが入力したパスワードが一致するかを確認します。データベースに保存されているユーザーのハッシュ値からsalt値を抽出します。ユーザーが入力したパスワードと抽出したsalt値を使用して、新たなハッシュ値を生成し、新たに生成したハッシュ値と、データベースから取得したハッシュ値を比較します。一致すればパスワード認証が成功します。認証に失敗した場合、パスワードを空にして「メールアドレスまたはパスワードが一致しません」というエラーメッセージをログイン画面上に表示します。セキュリティの観点から、メールアドレスが正しいかどうかを利用者に知らせないようにするため、「メールアドレスまたはパスワードが一致しません」というメッセージにしています。以下の画像のように「メールアドレスまたはパスワードが一致しません」というメッセージを表示させます。
4. 認証成功時の処理
認証成功後、サーバー側とブラウザ側でそれぞれ以下の処理を行います。
[サーバー側の処理]
1. セッション情報の保存
サーバーは、ログインしたユーザーのID、名前、メールアドレスなどの必要な情報をセッションに保存します。これにより、ユーザーのログイン状態をサーバー上で管理します。セッション情報はサーバー側に安全に保存され、外部から直接アクセスすることはできません。
2. セッションIDの発行
サーバーは、ログイン状態を識別するための一意のセッションIDを発行します。このセッションIDは、サーバー内でセッション情報に紐付けられています。
3. ログイン後画面へのリダイレクト
認証成功後、ユーザーは検索画面などのログイン後画面にリダイレクトされます。
[ブラウザ側の処理]
1. セッションIDの保存
サーバーが発行したセッションIDは、ブラウザがCookieとして保存します。このCookieは、ブラウザ内に自動的に管理され、サーバーとクライアントのやり取りに利用されます。
2. セッションIDの送信
ブラウザは、保存したセッションIDをサーバーへのリクエストに自動的に添付します。この仕組みによって、サーバーはセッションIDを基にユーザーを識別し、ログイン状態を維持します。
参考: PHPでセッションを使ったログインページを作ってみる|やまでぃーのブログ
以上がログイン機能についての説明でした。
ログアウト機能
続けてログアウト機能について説明します。
ログアウトは、ログイン状態でのみ行うことができます。
ログアウト処理は、以下のステップで進められます。
1. サーバー側のセッション変数の初期化
2. ブラウザ側のセッションIDの削除
3. サーバー側のセッションIDの無効化
各ステップの詳細は以下をご覧ください。
1. サーバー側のセッション変数の初期化
セッション変数の全データを空にし、セッション情報をリセットします。これにより、セッション変数が初期化され、ユーザー情報などのセッションデータが破棄されます。
2. ブラウザ側のセッションID削除
クライアントのブラウザ側にCookieとして記録されているセッションIDの破棄を行います。セッション管理にCookieを使用している場合はブラウザ側のCookieを削除しておかないとセッションIDが残ってしまいセキュリティ上よくありません。(実装段階では、調べが行き届いておらずブラウザ側でのセッションID削除は行いませんでした。)
3. サーバー側のセッションIDの無効化
セッション自体を破棄し、セッションIDも無効化して完全なログアウト状態にします。セッションの破棄が完了後、ログイン前の画面にリダイレクトします。今回の場合、以下の画像のようにトップ画面にリダイレクトします。
以上がログアウト機能についての説明でした。
参考:
PHP: session_destroy – Manual
PHPでセッションを完全に破棄する方法 – プログラマはサイコロを振らない
まとめ
ログイン/ログアウト機能を実装する際に、セッションやCookieの仕組みについて深く学ぶことができました。例えば、ChromeでAmazonにログインした後、EdgeでAmazonのURL(https://www.amazon.co.jp/)にアクセスした場合にログイン状態が維持されるのか、また、Chromeの別タブで同じURLを開いた場合にログイン状態が共有されるのかを検証しました。この検証を通じて、セッションやCookieがブラウザごと、またはタブごとにどのように扱われるかを具体的に確認しました。その結果、ログイン状態がどのように管理されているのかについて理解が深まりました。
今回学んだ知識を活かし、次はPHPフレームワークであるLaravelを使った実装に取り組んでいきたいと思います。Laravelでは、認証機能やセッション管理に便利な仕組みが既に用意されており、活用することでより効率的かつ安全なログイン/ログアウト機能を実装できるようなので、実装方法をしっかり学習したいと思います。将来的に、ユーザーに安心して使ってもらえるシステム構築ができるよう引き続き学習していきます。