ログイン画面を作ろう

問題のデータを入れるために管理画面が必要になりました。

ただ、その管理画面は筆者以外には触らせるわけにはいけません。

その管理画面を作るにあたっての方法をお伝えします。

目次

ログイン情報ファイルを作ろう

今回は、Basic認証ではなく、自分で作ります。

下準備として、ログイン情報を記載したPHPファイルを作ります。

PHP(config/admin.php)
<?php
return [
    'id' => 'ログインID',
    'password_hash' => password_hash('ログインパスワード', PASSWORD_DEFAULT),
];
?>

パスワードはベタ書きするのではなく、ハッシュ値にしてしまった方が、簡単には読み取れないので安心です。

これで準備完了です。

ログイン画面を作ろう

これが今回のメインになる画面作りです。

PHP(login.php)
<?php
session_start();

if (!empty($_SESSION['admin_logged_in'])) {
  header('Location: index.php'); // ← ログイン後の画面
  exit;
}

$error = '';
if ($_SERVER['REQUEST_METHOD'] === 'POST') {
  $config = require __DIR__ . './config/admin.php';

  if (
    $_POST['id'] === $config['id'] &&
    password_verify($_POST['password'], $config['password_hash'])
  ) {
    $_SESSION['admin_logged_in'] = true;
    header('Location: index.php'); // ← ログイン後の画面
    exit;
  } else {
    $error = 'ID またはパスワードが違います';
  }
}
?>
HTML(login.php)
<form method="post" class="bg-white p-6 rounded shadow w-80">
  <h1 class="text-xl font-bold mb-4">管理者ログイン</h1>

  <?php if ($error): ?>
    <p class="text-red-600 mb-3"><?= htmlspecialchars($error) ?></p>
  <?php endif; ?>

  <input name="id" placeholder="ID" required
    class="w-full mb-3 border rounded p-2">

  <input type="password" name="password" placeholder="Password" required
    class="w-full mb-4 border rounded p-2">

  <button class="w-full bg-teal-600 text-white py-2 rounded">
    ログイン
  </button>
</form>

まず、サーバー側でセッションを作成しておきます(ここ重要)

今回は「admin_logged_in」という名前で作っています。

その後、ログインIDとパスワードを入力し、ログインボタンを押下すると、

先ほど作成したconfig.phpのログインIDとパスワードと合致しているか確認します。

  • 合致している → ログイン後の画面にリダイレクト + ログインセッションをtrueにしておく
  • 合致していない → 再びログイン画面を表示し、エラーを表示

認証チェックファイルを作ろう

ログインできました!

めでたしめでたし~と思うのはまだ早い。

管理画面でしか表示されない画面に、先ほど作った ログインセッションがあるかどうかを確認する必要があります。

PHP(auth.php)
session_start();

if (empty($_SESSION['admin_logged_in'])) {
  header('Location: /login.php');
  exit;
}

「admin_logged_in」というセッションが無ければ、ログイン画面にリダイレクトするというだけ書かれたファイルですが、

これ、本当に重要です。

ちゃんとログイン画面を通じて、ログインしましたということを証明するのがセッション頼りなので、

このファイルをログイン後の各画面のグローバル変数として読み込みます。

PHP(ログイン後の各画面の一番上)
require_once __DIR__ . '/auth.php';

これを書き忘れた管理画面は普通に表示されてしまうので、書き忘れないように気を付けてくださいね!

ログアウトボタンを作ろう

ログインしたら必要なのがログアウトのロジック。

ログアウトボタンを押されたら、ログイン画面に遷移する作りにします。

HTML(ログイン後の各画面)
<a href="/logout.php" class="float-right mr-2 p-2 rounded text-white bg-red-500 hover:bg-red-600">ログアウト</a>
PHP(logout.php)
session_start();
session_destroy();
header('Location: login.php');
exit;

ログアウトボタンは適当に作って大丈夫ですが、

各画面に入れるのが面倒であれば、<header> の中に入れるのもありかと思います。

ログアウトボタンが押されたら、セッションを破棄した上でログイン画面にリダイレクトするというロジックになっています。

CSRF対策をしよう

なりすまし対策としてCSRF対策をします。

別の記事でもCSRF対策を紹介しているので、そこで作っていれば下記のPHPファイルの作成は飛ばしてください。

PHP(csrf.php)
<?php
session_start();

function generateCsrfToken(): string
{
  if (empty($_SESSION['csrf_token'])) {
    $_SESSION['csrf_token'] = bin2hex(random_bytes(32));
  }
  return $_SESSION['csrf_token'];
}

function validateCsrfToken(string $token): void
{
  if (
    empty($_SESSION['csrf_token']) ||
    !hash_equals($_SESSION['csrf_token'], $token)
  ) {
    http_response_code(403);
    exit('不正なリクエストです(CSRF)');
  }
}

上記が出来ていれば、ログイン画面に組み込みます。

PHP(login.php)
session_start();

require_once __DIR__ . '/csrf.php'; // ← 追加

if (!empty($_SESSION['admin_logged_in'])) {
  header('Location: index.php');
  exit;
}

$error = '';

$csrfToken = generateCsrfToken(); // ← 追加
HTML(login.php)
<form method="post" class="bg-white p-6 rounded shadow w-80">
  <input type="hidden" name="csrf_token" value="<?= htmlspecialchars($csrfToken) ?>">
  ...
</form>

トークンの埋め込みは上記でOKです。

PHP(login.php)
if ($_SERVER['REQUEST_METHOD'] === 'POST') {
  validateCsrfToken($_POST['csrf_token'] ?? ''); // ← 追加

  $config = require __DIR__ . './config/admin.php';
  ...
}

POSTされた時にトークンの確認を行い、OKなら通常の処理を行います。

これでCSRF対策は万全です!

これでログイン画面が出来上がりました。

  • URLをコピーしました!
目次