PHPのセッション(session_start)でログイン状態を保持する方法

phpアイキャッチ PHP

こんにちは、かつコーチです。

前回は $_GET$_POST でフォームの値を受け取る方法を解説しました。

今回は、その続きとして「ログインしたあと、ページを移動してもログイン状態が保たれる仕組み」であるセッションを解説します。

前回学んだ $_POST は、フォームを送信した1回のリクエストの間だけ値を持っている変数でした。

しかし、ログイン機能を作るには、ログインフォームを送信したあと、別のページに移動しても「この人はログイン済みだ」という情報を保持し続ける仕組みが必要です。

そこで登場するのが、今回解説するセッションです。

セッションとは

なぜ「状態の保持」が必要なのか

HTTP通信には、ステートレスという性質があります。

これは、「1回のリクエストが終わったら、サーバーはそのやり取りの内容を覚えていない」という意味です。

例えば、ログインページでIDとパスワードを送信して認証に成功したとしても、次にマイページへ移動したときには、サーバーは「さっき誰がログインしたか」を覚えていません。

そのままだと、ページを移動するたびに毎回ログインし直す必要が出てきてしまいます。

これでは実用的なWebアプリケーションになりません。

セッションの仕組み

この問題を解決するのがセッションという仕組みです。

セッションは、サーバー側に「このユーザーの情報」を一時的に保存しておき、ブラウザには「どのセッション情報を参照すればいいか」を示す小さな識別子(セッションID)だけを渡す、という仕組みです。

  1. ユーザーがログインに成功する
  2. サーバーがセッションIDを発行し、ブラウザのクッキーに保存させる
  3. ユーザーが別のページに移動すると、ブラウザは自動的にそのセッションIDを送信する
  4. サーバーはセッションIDを見て「このユーザーはログイン済みだ」と判断する

「サーバー側に保存された情報を、セッションIDという鍵で参照する」というイメージを持っておくと理解しやすいです。

セッションの基本的な使い方

session_start()で始める

PHPでセッションを使うには、まず session_start() をページの一番最初に書く必要があります。

<?php
session_start(); // セッションを開始する(必ず何かを出力する前に書く)

$_SESSION["username"] = "かつコーチ";
echo "セッションにユーザー名を保存しました";

session_start() を呼び出すと、$_SESSION というスーパーグローバル変数が使えるようになります。

$_SESSION に値を代入すると、その値がサーバー側に保存され、同じセッションIDを持つ別のページからも参照できるようになります。

別のページでセッションの値を使う

<?php
// mypage.php
session_start(); // このページでもセッションを開始する必要がある

if (isset($_SESSION["username"])) {
    echo $_SESSION["username"] . "さん、ようこそ!";
} else {
    echo "ログインしていません";
}

login.php$_SESSION["username"] に値を入れておけば、別のファイルである mypage.php でも、session_start() さえ呼んでおけば同じ値を参照できます。

これが「ページをまたいでログイン状態を保持する」仕組みの正体です。

ログイン機能を実装する流れ

ログイン処理の基本形

前回解説した $_POST とあわせて、簡単なログイン処理の流れを見てみましょう。

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

$inputId = $_POST["user_id"] ?? "";
$inputPassword = $_POST["password"] ?? "";

// 本来はデータベースと照合する処理が入る(ここでは簡略化)
$correctId = "katsu";
$correctPassword = "sample1234";

if ($inputId === $correctId && $inputPassword === $correctPassword) {
    $_SESSION["user_id"] = $inputId;
    $_SESSION["is_logged_in"] = true;
    header("Location: mypage.php");
    exit;
} else {
    echo "IDまたはパスワードが違います";
}

認証に成功したら $_SESSION にログイン情報を保存し、header("Location: ...") でマイページへ移動させています。

ログイン状態を確認するページ

マイページ側では、セッションを確認して「ログインしていなければログインページに戻す」処理を入れておくのが基本です。

<?php
// mypage.php
session_start();

if (!isset($_SESSION["is_logged_in"]) || $_SESSION["is_logged_in"] !== true) {
    header("Location: login.php");
    exit;
}

echo $_SESSION["user_id"] . "さん専用のマイページです";

この確認処理を、ログインが必要な全ページの先頭に入れることで、「ログインしていないユーザーが直接URLを打ち込んでマイページに入る」ことを防げます。

ログアウト処理

ログアウトは、保存しておいたセッションの情報を破棄する処理です。

<?php
// logout.php
session_start();

$_SESSION = []; // セッション内の情報をすべて空にする
session_destroy(); // セッション自体を破棄する

header("Location: login.php");
exit;

session_destroy() だけでも動作しますが、$_SESSION = [] で中身を先に空にしておくと、より確実に情報が残らなくなります。

つまずきやすいポイント:出力済みエラー

かつコーチが実際にハマったエラー

私が初めてセッションを使ったとき、次のエラーに何度も悩まされました。

Warning: session_start(): Session cannot be started after headers have already been sent in /var/www/html/mypage.php on line 5

原因は、session_start() を書く前に、HTMLタグや空白文字など、何かしらの出力をしてしまっていたことでした。

❌ Before:session_start()の前に出力がある

<?php
echo "マイページへようこそ"; // ここで先に出力してしまっている

session_start(); // すでに出力が始まった後なのでエラーになる
$_SESSION["visited"] = true;

セッションはブラウザとの間でクッキーをやり取りする仕組みのため、HTTPヘッダーへの書き込みが必要です。

しかし、一度でも画面に何かを出力してしまうと、PHPはその時点でヘッダー部分の送信を確定させてしまい、後からセッション用のヘッダーを追加できなくなります。

私の場合、原因は「PHPファイルの <?php タグの前に、見えない空白や改行がある」という単純なミスでした。

エディタの設定でファイル末尾に余分な改行が自動挿入されていたことに気づかず、半日近く原因を探し回った記憶があります。

✅ After:session_start()をファイルの一番先頭に書く

<?php
session_start(); // ファイルの一番最初、何も出力する前に呼び出す

echo "マイページへようこそ"; // この後なら自由に出力できる
$_SESSION["visited"] = true;

session_start() は、PHPファイルの中で一番最初に実行される処理として書くのが鉄則です。

エラーが出た場合は、<?php タグの前後に余分な空白や改行が入っていないか、ファイルの文字コード(BOM付きになっていないか)もあわせて確認してみてください。

セッションのセキュリティで意識しておきたいこと

セッションIDの再生成

ログインに成功したタイミングで、セッションIDを再生成しておくと安全性が高まります。

<?php
session_start();

// 認証成功後
session_regenerate_id(true); // セッションIDを再生成し、古いIDは破棄する
$_SESSION["user_id"] = $inputId;

session_regenerate_id(true) を呼ぶことで、ログイン前後でセッションIDが切り替わり、「セッション固定攻撃」と呼ばれる、他人のセッションIDを不正に使い回す攻撃への対策になります。

ログイン処理を実装する際は、認証成功の直後にこの1行を入れておく習慣をつけておくと安心です。

セッションだけに頼らない設計

セッションはサーバーが再起動されたり、有効期限が切れたりすると消えてしまいます。

「ログイン状態を長期間保持したい(次回訪問時も自動ログインさせたい)」という要件がある場合は、次回解説するクッキーと組み合わせて実現するのが一般的です。

セッションは「今の閲覧中に限った状態保持」、クッキーは「ブラウザに情報を残して次回以降も使う仕組み」と、役割が少し異なる点を押さえておいてください。

まとめ

この記事のポイント

  • HTTP通信はステートレスなため、ページ間で状態を保持するにはセッションの仕組みが必要
  • session_start() を呼ぶことで $_SESSION にサーバー側の情報を保存・参照できる
  • ログイン処理では認証成功時に $_SESSION へ情報を保存し、各ページの先頭でログイン確認を行う
  • session_start() は出力より前、ファイルの一番先頭で呼び出す必要がある
  • ログイン成功時は session_regenerate_id(true) でセッションIDを再生成し、セッション固定攻撃を防ぐ

次に読むべき記事

セッションでログイン状態を保持できるようになったら、次はブラウザに情報を残す「クッキー」の使い方を見ていきましょう。

→ 次の記事:PHPのクッキー(setcookie)の使い方と注意点

タイトルとURLをコピーしました