セッション(session)とは

## はじめに
私自身、『セッション(session)ついて人から質問された際に、納得してもらえるような説明ができるぐらい理解を深めたい』という思いから今回の記事を書くことにしました。

記事の中に間違いがありましたらご指摘いただけると幸いです。

## そもそもセッションとは
セッションについては既にQiitaさんに沢山の素晴らしい記事が投稿されていますが、個人的に以下の記事がわかりやすいと思いました。

https://qiita.com/hththt/items/07136ad74127999df271

https://qiita.com/shimotaroo/items/e4a1011d040ffc7f56f6

セッションについてはクッキーとセットで使われることが多いと思いますが、今回クッキーについての詳細な説明は割愛させていただきます。

## セッションはどういった機能を実現するために使用されるか
セッションが使われている具体例として、以下が挙げられます。
* ユーザー認証
* カートの管理
* フォームから送信されたデータの保持
* バリデーションのエラーメッセージ

上記以外にも様々な使用場面が考えられます。

今回は上記の中から**ユーザー認証をピックアップし**、どのような流れでセッションが使用されているかを確認し、セッションについての理解を深めたいと思います。

## ユーザー認証の流れ(ログイン状態の有無、ログアウトも含む)
**一般的なMPAアプリケーション(Multi-Page Application)において、セッションを使ったユーザー認証(1、2、3、4、5)、ユーザーのログイン状態の有無確認(6、7)、ログアウト(8)の流れが以下になります。**

1\. ユーザーがアプリケーションにアクセスして、ログインページに飛ぶ。
2\. ユーザー名とパスワードを入力してログイン。
3\. 入力された情報はサーバーに送信され、サーバー側でユーザー認証が行われる。
4\. サーバーはユーザー名とパスワードの組み合わせを確認し、認証が成功した場合はセッションを作成、セッションIDをクッキー(cookie)を通じてブラウザに保存。
5\. ユーザーは認証が成功したことを示すメッセージを受け取る。
6\. ユーザーがアプリケーション内の別のページに移動するたびに、ブラウザはセッションIDをサーバーに送信。
7\. サーバーは受け取ったセッションIDを使用してセッションを特定し、ユーザーの認証状態を確認。
8\. ユーザーがログアウトする場合、サーバーはブラウザに保存されているセッションIDを削除し、サーバー側のセッションデータも削除する。

**上記の中で、セッションが出てくる個所(4、7、8)をコードも交えて補足説明していきます。それ以外の個所はセッションがPHP側のコードに含まれないので割愛させていただきます。**

## 4. サーバー側でのユーザー認証とセッション情報を保存
```php: login.php
<?php
session_start();

// ログインフォームから送信されたユーザー名とパスワードの取得
$username = $_POST['username'];
$password = $_POST['password'];

/* ユーザー名とパスワードの検証
（仮の条件として、ユーザー名が "admin"、パスワードが "password" であると認証。
本来はDBにユーザー名を問い合わせ、ユーザーが存在した場合、ハッシュ化されたパスワードと比較を行う）
*/
if ($username === 'admin' && $password === 'password') {
    // 認証成功時の処理

    // セッションにユーザー情報を格納
    $_SESSION['username'] = $username;

    // セッションIDをクッキーに保存
    $sessionId = session_id();
    setcookie('PHPSESSID', $sessionId, time() + 3600, '/');

    // ログイン後のリダイレクトなどの処理
    header('Location: dashboard.php');

} else {
    // 認証失敗時の処理
    echo 'ユーザー名またはパスワードが間違っています。';
}
?>
```

このコードでは、ユーザーがログインフォームから送信したユーザー名とパスワードを検証し、認証が成功した場合にセッションにユーザー情報を格納し、セッションIDをクッキーに保存します（setcookie関数を使用）。ログイン成功後は、header関数を使用してリダイレクトなどの適切な処理を行います。

このようにセッションを使用してユーザー情報を保存することでページ遷移の際に、ユーザーのログイン状態の有無を確認できるようになります。

## 7. セッションを特定し、ユーザーの認証状態を確認。

```php: isLogin.php
<?php
session_start();

// ログインしているユーザーかどうか判定
if (isset($_SESSION['username'])) {
    
    // ログインユーザーだと証明されたのでtrueを返却。
    return true;

} else {
    // ログインしていないユーザーの場合の処理
    header('Location: login.php');
    exit();
}
?>
```

このコードは主にページ遷移した際に、ログインしているユーザーのみにページ表示させる場面で使用されます。ユーザーがログインしている場合は処理を続行し、ログインしていない場合はログインページにリダイレクトすることで、認証の要件を満たさないユーザーを制御します。


## 8. ログアウトを行い、ブラウザとサーバーのセッション情報を削除。

```php: logout.php
<?php
session_start();
 
// セッション変数を全て解除する
$_SESSION = array();
 
// セッションを切断するにはセッションクッキーも削除する。
// Note: セッション情報だけでなくセッションを破壊する。
if (ini_get("session.use_cookies")) {
    $params = session_get_cookie_params();
    setcookie(session_name(), '', time() - 42000,
        $params["path"], $params["domain"],
        $params["secure"], $params["httponly"]
    );
}
 
// 最終的に、セッションを破壊する
session_destroy();

// ログアウト後のリダイレクト処理
header('Location: login.php');
?>
```

このコードはセッションを破棄し、ユーザーをログアウトさせる際に使用されます。セッション変数を解除し、セッションクッキーを削除してセッションを無効化し、最後にセッションを破壊します。ログアウト後には指定されたページにリダイレクトされます。

上記のコードはPHPのドキュメントに記載されている、セッションを破壊するコードとほぼ一緒です。参考までにURLを下記に貼っておきます。

https://www.php.net/manual/ja/function.session-destroy.php