PHPでログイン時にセッションIDの変更

まずは単純にログインをする

<?php

session_start();

echo 'セッションID: ' . session_id() . "\n";

if (!isLogin()) {
    echo "Start to login\n";
    login();
} else {
    echo "already logged in\n";
}

echo 'セッションID: ' . session_id() . "\n";

function login()
{
    $_SESSION['login'] = true;
}

/**
 * @return bool
 */
function isLogin()
{
    return (bool) $_SESSION['login'];
}

1回目のアクセス

セッションID: ka0a429ht11vq1ehbkom3fek2n
Start to login
セッションID: ka0a429ht11vq1ehbkom3fek2n

2回目の以降のアクセス

セッションID: ka0a429ht11vq1ehbkom3fek2n
already logged in
セッションID: ka0a429ht11vq1ehbkom3fek2n

となり、ログインができるがセッションIDは変更されない

ログイン時にセッションIDを変更する

<?php

session_start();

echo 'セッションID: ' . session_id() . "\n";

if (!isLogin()) {
    echo "Start to login\n";
    login();
} else {
    echo "already logged in\n";
}

echo 'セッションID: ' . session_id() . "\n";

function login()
{
    session_regenerate_id(true);

    $_SESSION['login'] = true;
}

/**
 * @return bool
 */
function isLogin()
{
    return (bool) $_SESSION['login'];
}

1回目のアクセス

セッションID: 5ae9gjof2qhdhh7gcduqbpugn8
Start to login
セッションID: vul4fl9t26cq0uhpq0it4fq4sh

2回目の以降のアクセス

セッションID: ka0a429ht11vq1ehbkom3fek2n
already logged in
セッションID: ka0a429ht11vq1ehbkom3fek2n

となり、ログイン前にセッションIDが変更されている

セッションをDBに保存するタイプでログイン時にセッションIDを変更する

セッション保存ようのテーブルを作成する

CREATE TABLE `session_storage` (
  `session_id` varchar(255) NOT NULL,
  `session_data` longtext NOT NULL,
  `session_time` bigint(20) NOT NULL,
  PRIMARY KEY (`session_id`)
);
<?php

define('DB_HOST', 'localhost');
define('DB_NAME', 'test');
define('DB_USER', 'root');
define('DB_PASS', 'password');

class MySessionHandler implements SessionHandlerInterface
{
    /**
     * @var PDO
     */
    protected $db;

    /**
     * @return bool|void
     */
    public function close()
    {
        $this->db = null;

        return true;
    }

    /**
     * @param string $session_id
     * @return bool
     */
    public function destroy($session_id)
    {
        $sql = 'DELETE FROM session_storage WHERE session_id = ?';
        $stmt = $this->db->prepare($sql);
        return $stmt->execute([$session_id]);
    }

    /**
     * @param int $maxlifetime
     * @return bool
     */
    public function gc($maxlifetime)
    {
        $sql = 'DELETE FROM session_storage WHERE session_time < ?';
        $stmt = $this->db->prepare($sql);
        return $stmt->execute([(time() - $maxlifetime)]);
    }

    /**
     * @param string $save_path
     * @param string $name
     * @return bool
     */
    public function open($save_path, $name)
    {
        $db = new PDO('mysql:host=' . DB_HOST . '; dbname=' . DB_NAME, DB_USER, DB_PASS);
        $db->setAttribute(PDO::ATTR_ERRMODE, PDO::ERRMODE_EXCEPTION);

        if (!$db) {
            die('DB接続失敗');
        }
        $this->db = $db;

        return true;
    }

    /**
     * @param string $session_id
     * @return string
     */
    public function read($session_id)
    {
        $session_data = '';

        $sql = ' SELECT';
        $sql .= '   session_data';
        $sql .= ' FROM';
        $sql .= '   session_storage';
        $sql .= ' WHERE';
        $sql .= '   session_id = ?';
        $sql .= '   AND session_time > ? ';

        $stmt = $this->db->prepare($sql);
        $stmt->execute([$session_id, time() - ini_get('session.gc_maxlifetime')]);

        if ($row = $stmt->fetch(PDO::FETCH_ASSOC)) {
            $session_data = $row['session_data'];
        }

        return $session_data;
    }

    /**
     * @param string $session_id
     * @param string $session_data
     * @return bool
     */
    public function write($session_id, $session_data)
    {
        $sql = 'SELECT * FROM session_storage WHERE session_id = ?';
        $stmt = $this->db->prepare($sql);
        $stmt->execute([$session_id]);

        if ($stmt->fetch(PDO::FETCH_ASSOC)) {
            $sql = 'UPDATE session_storage SET session_data = ?, session_time = ? WHERE session_id = ?';
            $stmt = $this->db->prepare($sql);
            return $stmt->execute([$session_data, time(), $session_id]);
        }

        $sql = 'INSERT INTO session_storage (session_id, session_data, session_time) ';
        $sql .= ' VALUES (?, ?, ?)';
        $stmt = $this->db->prepare($sql);
        return $stmt->execute([$session_id, $session_data, time()]);
    }
}

$session_handler = new MySessionHandler();
session_set_save_handler($session_handler, true);

session_start();

echo 'セッションID: ' . session_id() . "\n";

if (!isLogin()) {
    echo "Start to login\n";
    login();
} else {
    echo "already logged in\n";
}

echo 'セッションID: ' . session_id() . "\n";

function login()
{
    session_regenerate_id(true);

    $_SESSION['login'] = true;
}

/**
 * @return bool
 */
function isLogin()
{
    return (bool)$_SESSION['login'];
}

1回目のアクセス

セッションID: qo99kgbopvijf1v5aj9bhkssr5
Start to login
セッションID: meo8ef2kuplvs3m6mf6p5g0ks4

2回目の以降のアクセス

セッションID: meo8ef2kuplvs3m6mf6p5g0ks4
already logged in
セッションID: meo8ef2kuplvs3m6mf6p5g0ks4