PHPでセッションを使ったログインページを作ってみる

PHP PHPでセッションを使ったログインページを作ってみる

 

セッションの仕組みを理解するにはログインページを一度作成してみるのがいいとうことで、今回はセッションログインの仕組みとPHPでログインページの作成の仕方をメモとして残しておきます。

 

セッションログインの仕組み

 

まずはセッションログインの仕組みを勉強します。

そのためにはクッキーとセッションについて知る必要があります。

 

  • クッキー:ユーザー側のコンピュータに保存されているデータ
  • セッション:サーバー側に保存されているデータ

 

セッションログインの際にはこの2つを利用して認証を行います。全体の流れは以下の通りです。

 

  1. ユーザーがログインに成功。
  2. クッキーにセッションid(鍵のようなもの)を保存しセッションにログイン状態を記録。セッションに保存された情報にはセッションidがないとアクセスできません。
  3. 認証が必要な画面でセッションidをもとにログイン状態を照合する。
  4. 照合に成功した場合、ログイン後のページを表示することができる。
  5. ログアウトされたら、セッションの情報とクッキーのセッション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>

 

最後に

 

ここまでの内容でログイン〜ログアウトの一連の流れは作成できました。

最初に登録したユーザー名とパスワードで早速ログインを試してみましょう。

必要に応じて新規ユーザー登録ページなどを拡張していくこともできると思いますので、是非試してみてください。