Parallels Desktop 5% OFFクーポンCheck!

【PHP入門】ログイン機能を実装する方法 セッションの使い方

PHPでログイン機能を実装する方法

PHPでログイン機能を実装する方法をできるだけ簡単に解説します。

目次

ユーザ登録

メールアドレスとパスワードを使って認証するログインシステムを作ります。ユーザデータはMySQLに保存します。

//フォームから受け取った値を変数に代入
$email = $_POST['email'];
$password = password_hash($_POST['password'], PASSWORD_DEFAULT);

//データベース接続情報
$dbuser = '***';
$dbpass = '***';
$dsn = 'mysql:host=***;dbname=***;';

//MySQL接続
try {
  $dbh = new PDO($dsn, $dbuser, $dbpass);
} catch (PDOException $e) {
  exit('データベース接続失敗: ' . $e->getMessage());
}

//メールアドレスがすでに登録されていないかチェック
$sql = 'SELECT * FROM users WHERE email = :email';
$sth = $dbh->prepare($sql);
$sth->bindValue(':email', $email);
$sth->execute();
$result = $sth->fetch(PDO::FETCH_ASSOC);

//登録されている場合
if ($result['email'] == $email) {
  echo 'メールアドレスがすでに登録されているため、ユーザ登録できませんでした';
  //登録されていない場合
} else {
  $sql = 'INSERT INTO users (email, password) VALUES (:email, :password)';
  $sth = $dbh->prepare($sql);
  $sth->bindValue(':email', $email);
  $sth->bindValue(':password', $password);
  $sth->execute();
  echo 'ユーザ登録が完了しました';
}

MySQLのusersテーブルには次のようにデータが格納されます。

+--------------------+--------------------------------------------------------------+
| email              | password                                                     |
+--------------------+--------------------------------------------------------------+
| ******@oopsoop.com | $2y$10$fFQCVzFHq21lpajRcxqCwuCR4Hno2AgKWpwb9QbbA.Rb7syd3echy |
+--------------------+--------------------------------------------------------------+

フォームから受け取った値を変数に代入

フォームからPOSTメソッドで送信されたデータは$_POST変数に入っていますので、これを変数に代入します。今回は省略しますが、ここでバリデーションやサニタイジングをします。

password_hash関数でパスワードをハッシュ化しています。

ハッシュ化とは

ハッシュ化とは文字列を一定のルールに従って別の文字列(ハッシュ値)に変換することです。

暗号化と似ていますが、暗号が復号できるのに対してハッシュ値は元に戻すことができません。なので、パスワードをサーバに保存するときはハッシュ化します。もしハッシュ値を盗まれたとしても元のパスワードを知られることがないからです。

人様からお預かりしたパスワードをそのままサーバに保存するなんてことは絶対にしてはいけません。

メールアドレスがすでに登録されていないかチェック

メールアドレスがすでに登録されていたら処理を中断します。登録されていなければメールアドレスとパスワードのハッシュ値をデータベースに登録します。

ログイン

ログインフォームからメールアドレスとパスワードを受け取ったら、次のように処理します。

//セッションの開始
session_start();

//フォームから受け取った値を変数に代入
$email = $_POST['email'];;
$password = $_POST['password'];;

//データベース接続情報
$dbuser = '***';
$dbpass = '***';
$dsn = 'mysql:host=***;dbname=***;';

//MySQL接続
try {
  $dbh = new PDO($dsn, $dbuser, $dbpass);
} catch (PDOException $e) {
  exit('データベース接続失敗: ' . $e->getMessage());
}

//DBからユーザ情報を取得
$sql = 'SELECT * FROM users WHERE email = :email';
$sth = $dbh->prepare($sql);
$sth->bindValue(':email', $email);
$sth->execute();
$result = $sth->fetch(PDO::FETCH_ASSOC);

//パスワードが正しいかチェック
//パスワードが正しい場合
if (password_verify($password, $result['password'])) {
  //情報をセッション変数に登録
  $_SESSION['email'] = $result['email'];
  echo 'ログインしました';
} else {
  //パスワードが間違っている場合
  echo 'メールアドレスまたはパスワードが間違っています';
}

セッションの開始

session_start関数でセッションを開始します。

セッションとはウェブサイトを訪問したユーザの固有の情報をサーバに保持する機能です。ユーザが今ログイン中なのかそうでないのかをセッション機能を使って判別します。

パスワードが正しいかチェック

password_verify関数を使ってパスワードが正しいかチェックします。第1引数にフォームから受け取ったパスワード、第2引数にDBから取り出したパスワードのハッシュを渡します。合っていればtrue、違っていればfalseが返されます。

このようにpassword_hash関数でハッシュ化したパスワードはpassword_verify関数で検証することができます。

情報をセッション変数に登録

セッション変数$_SESSIONに何らかのデータを代入します。このセッション変数に値が入っていればログイン中、入っていなければログイン中ではないということになります。

セキュリティ担当大臣からのお願い

ログインに失敗したときのエラーメッセージは曖昧なものにしましょう。この例では「メールアドレスまたはパスワードが間違っています」としています。

「メールアドレスは合っていますが、パスワードが違います」のようなメッセージのほうが親切だと思いませんか?でも、それでは不正アクセスを試みる輩にメールアドレスは合っているというヒントを与えてしまうことになります。

ログイン関連のエラーメッセージはぼやかすということを覚えておいてください。

ログアウト

//セッションの開始
session_start();

//セッション変数の中身を空にする
$_SESSION = array();

//クライアント側のセッションを破棄(省略可)
if (isset($_COOKIE[session_name()])) {
  setcookie(session_name(), '', time() - 42000, '/');
}

//サーバ側のセッションを破棄
session_destroy();

echo 'ログアウトしました';

セッション変数の中身を空にする

$_SESSION空の配列を代入します。以下の手順でsession_destroyしてもセッション変数はリセットされないのでこの処理をする必要があります。

クライアント側のセッションを破棄

セッションを使うとブラウザのCookieにセッションIDが保存されるので、それを削除します。

Cookieの有効期限を過去の日時にすることで、Cookieを削除しています。time() - 42000の部分はtime() - 100でもtime() - 1でもいいのですが、公式マニュアルが-42000となっているので、このように書くことを我々は強制されています。

なお、この処理は省略してもOKです。なぜなら、次の手順のsession_destroyでサーバ側のセッションが破棄されれば、どっちみちこのセッションは使えなくなるからです。

サーバ側のセッションを破棄

session_destroy関数で、サーバ側のセッションを破棄します。

サーバ側のセッションの実体はテキストファイルで、そのテキストファイルが削除されます。

セッションの設定

セッションファイルの保存場所

サーバ側のセッションファイルの保存場所はPHPの設定ファイルphp.iniで設定します。

session.save_path = "/tmp"

上記のように/tmpディレクトリが設定されている場合が多いと思います。

自分だけが利用するサーバならばこのままでもいいのですが、共用レンタルサーバを利用している場合はセキュリティ的にアレです。というのは、/tmpディレクトリの中は誰でも見ることができるようになっているからです。もちろんセッションファイルの中身は見られないようなパーミッション設定になっていますがファイル名(=セッションID)はバレバレです。セッションファイルの保存場所をユーザディレクトリ下に変更したほうがよいでしょう。

セッションファイルの保存場所を変更するには、設定ファイル(php.ini,.user.ini, .htaccessなど)またはsession_save_path関数を使います。

php.ini, .user.ini などの設定方法

session.save_path = "/home/username/tmp"

.htaccess の設定方法

php_value session.save_path "/home/username/tmp"

スクリプト内で設定する方法

<?php
session_save_path('/home/username/tmp');

セッションの有効期限

セッションには有効期限があり、有効期限を過ぎるとセッションは破棄されます。つまり、ログイン状態が解除されます。

ログアウトしなかった場合に一定期間ログイン状態を維持したい場合は、セッションの有効期限を設定します。

session.gc_maxlifetime = 1440
session.gc_probability = 1
session.gc_divisor = 1000

上記のように設定されていれば、最終アクセスから1440秒(24分)後に1000分の1の確率でセッションが破棄されます。

つまり、session_startが実行されたときに、セッションファイルの更新日時がsession.gc_maxlifetime秒前より古ければsession.gc_divisor分のsession.gc_probabilityの確率でセッションファイルが削除されます。

24時間後に100%(1分の1)の確率でセッションを破棄したいならば次のように設定します。

php.ini, .user.ini などの設定方法

session.gc_maxlifetime = 86400
session.gc_probability = 1
session.gc_divisor = 1

.htaccess の設定方法

php_value session.gc_maxlifetime 86400
php_value session.gc_probability 1
php_value session.gc_divisor 1

スクリプト内で設定する方法

<?php
ini_set('session.gc_maxlifetime', 86400);
ini_set('session.gc_probability', 1);
ini_set('session.gc_divisor', 1);

有効期限を過ぎたセッションファイルの削除は、session.save_path内のすべてのファイルが対象となります。共用レンタルサーバを利用している場合は、他のユーザの設定によって予期しないタイミングでセッションファイルが削除されることがあります。これを避けるためにもsession.save_pathの設定を変更しましょう。

ブラウザを閉じてもログインを保存したい

上記の方法でセッションの有効期限を伸ばしたとしても、ブラウザを閉じればセッションは破棄されてしまいます。

なぜならば、クライアント側でセッションを保存するCookieの有効期限がデフォルトでは0になっているからです。

session.cookie_lifetime = 0

ブラウザにセッションの有効期限を覚えさせるには次のようにしてCookieの有効期限を設定します。

php.ini, .user.ini などの設定方法

session.cookie_lifetime = 86400

.htaccess の設定方法

php_value session.cookie_lifetime 86400

スクリプト内で設定する方法

<?php
ini_set('session.cookie_lifetime', 86400);

でわでわ

プログラミング学習、お疲れさまです

プログラミングの独学に行き詰まっていませんか?誰かに相談したい、もっと効率よく学びたいなら、プログラミングスクールを検討してみてください。

PHPでログイン機能を実装する方法

この記事が気に入ったら
いいね または フォローしてね!

シェアしてね

コメント

コメントする

目次