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
関数でパスワードをハッシュ化しています。
ハッシュ化とは文字列を一定のルールに従って別の文字列(ハッシュ値)に変換することです。
暗号化と似ていますが、暗号が復号できるのに対してハッシュ値は元に戻すことができません。なので、パスワードをサーバに保存するときはハッシュ化します。もしハッシュ値を盗まれたとしても元のパスワードを知られることがないからです。
人様からお預かりしたパスワードをそのままサーバに保存するなんてことは絶対にしてはいけません。必ずハッシュ化しましょう。
メールアドレスがすでに登録されていないかチェック
メールアドレスがすでに登録されていたら処理を中断します。登録されていなければメールアドレスとパスワードのハッシュ値をデータベースに登録します。
無料で利用できるプログラミング学習サービスをお探しならば Code Lesson はいかがでしょうか。プロのエンジニアが監修した学習ロードマップで効率的に学習、AIに質問、最後にクイズで理解度をチェックできます。
ログイン
ログインフォームからメールアドレスとパスワードを受け取ったら、次のように処理します。
//セッションの開始
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
となっているので、このように書くことを我々は強制されています。
サーバ側のセッションを破棄
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の確率でセッションが破棄されます。
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);
でわでわ
無料で利用できるプログラミング学習サービスをお探しならば Code Lesson はいかがでしょうか。プロのエンジニアが監修した学習ロードマップで効率的に学習、AIに質問、最後にクイズで理解度をチェックできます。
コメント