セッションの仕組みを理解するにはログインページを一度作成してみるのがいいとうことで、今回はセッションログインの仕組みとPHPでログインページの作成の仕方をメモとして残しておきます。
セッションログインの仕組み
まずはセッションログインの仕組みを勉強します。
そのためにはクッキーとセッションについて知る必要があります。
- クッキー:ユーザー側のコンピュータに保存されているデータ
- セッション:サーバー側に保存されているデータ
セッションログインの際にはこの2つを利用して認証を行います。全体の流れは以下の通りです。
- ユーザーがログインに成功。
- クッキーにセッションid(鍵のようなもの)を保存しセッションにログイン状態を記録。セッションに保存された情報にはセッションidがないとアクセスできません。
- 認証が必要な画面でセッションidをもとにログイン状態を照合する。
- 照合に成功した場合、ログイン後のページを表示することができる。
- ログアウトされたら、セッションの情報とクッキーのセッションidを消去。セッションが破棄されるので、ログイン後のページにはアクセスできなくなる。
ユーザー側にはセッションidのみが保存されていて、ログイン後の情報はサーバー側のセッションに保存されているので、他のユーザーからアクセスはされません。(セッションidを奪われた場合や推測された場合、セッションidを強要された場合は別ですが..)
セキュリティ対策についてはここには割愛しますので、ググって調べて見てください。
認証用データベース
ではログインを作成する前にデータベースの準備をしましょう。
今回は練習用なので、簡単に実装できるSQLiteを使用しています。
テーブル名はusersとしておき、用意しているフィールドは以下の通り。
- ID (INTEGER, AUTOINCREMENT, PRIMARY KEY)
- name (VARCHAR(10), UNIQUE)
- pass (VARCHAR(100))
CREATE TABLE users (id INTEGER PRIMARY KEY AUTOINCREMENT,
name VARCHAR(10) UNIQUE,
pass VARCHAR(100));
ここに初期データを登録しておきたいところですが、今回はpassに、ハッシュ化した値を入れるようにしていますので、password_hash関数でハッシュ化した値を登録しておきましょう。
password_hash('password', PASSWORD_DEFAULT);
//=> $2y$10$.vBA1.....
INSERT INTO users (name, pass) VALUES ('testuser', '$2$10.vBA1.....');
準備ができたところで、早速ログインページを作っていきます。
今回はログインページをindex.php, ログイン後のページをsuccess.php, ログアウトページをlogout.phpとしています。
ログインページを作成
index.phpとしてログインページを作成していきましょう。
<?php
//セッションを使うことを宣言
session_start();
//データベースに接続する
try {
$pdo = new PDO('sqlite:database.sqlite', '', '', [
PDO::ATTR_ERRMODE => PDO::ERRMODE_EXCEPTION,
PDO::ATTR_DEFAULT_FETCH_MODE => PDO::FETCH_ASSOC,
]);
}
catch (PDOExeption $e) {
exit ('データベースエラー');
}
//ログイン状態の場合ログイン後のページにリダイレクト
if (isset($_SESSION["login"])) {
session_regenerate_id(TRUE);
header("Location: success.php");
exit();
}
//postされて来なかったとき
if (count($_POST) === 0) {
$message = "";
}
//postされて来た場合
else {
//ユーザー名またはパスワードが送信されて来なかった場合
if(empty($_POST["uname"]) || empty($_POST["pass"])) {
$message = "ユーザー名とパスワードを入力してください";
}
//ユーザー名とパスワードが送信されて来た場合
else {
//post送信されてきたユーザー名がデータベースにあるか検索
try {
$stmt = $pdo -> prepare('SELECT * FROM users WHERE name=?');
$stmt -> bindParam(1, $_POST['uname'], PDO::PARAM_STR, 10);
$stmt -> execute();
$result = $stmt -> fetch(PDO::FETCH_ASSOC);
}
catch (PDOExeption $e) {
exit('データベースエラー');
}
//検索したユーザー名に対してパスワードが正しいかを検証
//正しくないとき
if (!password_verify($_POST['pass'], $result['pass'])) {
$message="ユーザー名かパスワードが違います";
}
//正しいとき
else {
session_regenerate_id(TRUE); //セッションidを再発行
$_SESSION["login"] = $_POST['uname']; //セッションにログイン情報を登録
header("Location: success.php"); //ログイン後のページにリダイレクト
exit();
}
}
}
$message = htmlspecialchars($message);
?>
<!DOCTYPE html>
<html lang="ja">
<head>
<meta charset="UTF-8">
<title>ログインページ</title>
<link href="login.css" rel="stylesheet" type="text/css">
</head>
<body>
<h1>ログインページ</h1>
<div class="message"><?php echo $message;?></div>
<div class="loginform">
<form action="index.php" method="post">
<ul>
<li>ユーザー名:<input name="uname" type="text"></li>
<li>パスワード:<input name="pass" type="password"></li>
<li><input name="送信" type="submit"></li>
</ul>
</form>
</div>
</body>
</html>
ログイン後のページ
ログインに成功したときに表示するページを作成していきます。名前はsuccess.phpとしておきます。
<?php
//セッションを使うことを宣言
session_start();
//ログインされていない場合は強制的にログインページにリダイレクト
if (!isset($_SESSION["login"])) {
header("Location: index.php");
exit();
}
//ログインされている場合は表示用メッセージを編集
$message = $_SESSION['login']."さんようこそ";
$message = htmlspecialchars($message);
?>
<!DOCTYPE html>
<html lang="ja">
<head>
<meta charset="UTF-8">
<title>ログイン成功ページ</title>
<link href="login.css" rel="stylesheet" type="text/css">
</head>
<body>
<h1>ログイン成功ページ</h1>
<div class="message"><?php echo $message;?></div>
<a href="logout.php">ログアウト</a>
</body>
</html>
ログアウトページ
では最後にログアウト処理をするページを作成します。名前はlogout.phpとします。
<?php
//セッションを使うことを宣言
session_start();
//ログインされていない場合は強制的にログインページにリダイレクト
if (!isset($_SESSION["login"])) {
header("Location: index.php");
exit();
}
//セッション変数をクリア
$_SESSION = array();
//クッキーに登録されているセッションidの情報を削除
if (ini_get("session.use_cookies")) {
setcookie(session_name(), '', time() - 42000, '/');
}
//セッションを破棄
session_destroy();
?>
<!DOCTYPE html>
<html lang="ja">
<head>
<meta charset="UTF-8">
<title>ログアウトページ</title>
<link href="login.css" rel="stylesheet" type="text/css">
</head>
<body>
<h1>ログアウトページ</h1>
<div class="message">ログアウトしました</div>
<a href="index.php">ログインページへ</a>
</body>
</html>
最後に
ここまでの内容でログイン〜ログアウトの一連の流れは作成できました。
最初に登録したユーザー名とパスワードで早速ログインを試してみましょう。
必要に応じて新規ユーザー登録ページなどを拡張していくこともできると思いますので、是非試してみてください。