Membuat Fitur Remember Me Multi Device Login (Token Unik per Perangkat) di PHP MySQL

By | 14 October 2025

Fitur Remember Me memberi kenyamanan bagi pengguna untuk tetap login tanpa harus memasukkan ulang username dan password setiap kali membuka situs. Namun dalam praktiknya, banyak sistem hanya mendukung satu token — artinya jika pengguna login dari perangkat baru, token lama dihapus dan sesi di perangkat lama terputus. Di era modern, pengguna sering mengakses akun dari banyak perangkat sekaligus — laptop, smartphone, dan tablet. Karena itu, kita perlu membuat sistem Remember Me multi device yang aman:

  • Token unik untuk setiap perangkat,

  • Validasi server-side terhadap token,

  • Dukungan logout spesifik per perangkat,

  • Perlindungan dari session hijacking.

Struktur Tabel Database

Kita akan menambahkan tabel baru remember_tokens yang menyimpan token login untuk setiap perangkat pengguna.

CREATE TABLE remember_tokens (
  id INT AUTO_INCREMENT PRIMARY KEY,
  user_id INT NOT NULL,
  selector CHAR(12) NOT NULL,
  hashed_token CHAR(64) NOT NULL,
  device VARCHAR(255),
  ip_address VARCHAR(50),
  user_agent VARCHAR(255),
  expires DATETIME NOT NULL,
  created_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP
);

Kolom penting:

  • selector → identifikasi token di cookie.

  • hashed_token → hasil hash token (disimpan aman di DB).

  • device dan user_agent → untuk mengenali perangkat.

  • expires → tanggal kedaluwarsa token.

Proses Login + Remember Me Multi Device

Ketika pengguna login dan mencentang Remember Me, sistem akan membuat token baru tanpa menghapus token lain milik user yang sama.

<?php
session_start();
include 'config.php';

if ($_SERVER['REQUEST_METHOD'] === 'POST') {
    $username = trim($_POST['username']);
    $password = $_POST['password'];
    $remember = isset($_POST['remember']);

    $stmt = $conn->prepare("SELECT * FROM users WHERE username=? OR email=?");
    $stmt->bind_param("ss", $username, $username);
    $stmt->execute();
    $result = $stmt->get_result();
    $user = $result->fetch_assoc();

    if ($user && password_verify($password, $user['password'])) {
        session_regenerate_id(true);
        $_SESSION['user_id'] = $user['id'];
        $_SESSION['username'] = $user['username'];

        // Jika Remember Me dicentang
        if ($remember) {
            $selector = bin2hex(random_bytes(6));
            $token = random_bytes(33);
            $hashedToken = hash('sha256', $token);
            $expires = date('Y-m-d H:i:s', time() + 86400 * 30); // 30 hari

            $device = $_SERVER['HTTP_USER_AGENT'];
            $ip = $_SERVER['REMOTE_ADDR'];

            // Simpan ke database (tanpa menghapus token lama)
            $stmt = $conn->prepare("INSERT INTO remember_tokens (user_id, selector, hashed_token, device, ip_address, user_agent, expires) VALUES (?, ?, ?, ?, ?, ?, ?)");
            $stmt->bind_param("issssss", $user['id'], $selector, $hashedToken, $device, $ip, $device, $expires);
            $stmt->execute();

            // Simpan ke cookie (selector|token)
            setcookie(
                'rememberme',
                $selector . ':' . bin2hex($token),
                time() + 86400 * 30,
                '/',
                '',
                true,  // Secure (gunakan HTTPS)
                true   // HttpOnly
            );
        }

        header("Location: dashboard.php");
        exit();
    } else {
        echo "<script>alert('Username atau password salah!');</script>";
    }
}
?>

Auto Login dari Cookie di Banyak Perangkat

Ketika pengguna membuka situs tanpa session, sistem akan memeriksa cookie rememberme dan memverifikasi token di database.

<?php
session_start();
include 'config.php';

if (!isset($_SESSION['user_id']) && isset($_COOKIE['rememberme'])) {
    list($selector, $token) = explode(':', $_COOKIE['rememberme']);

    $stmt = $conn->prepare("SELECT * FROM remember_tokens WHERE selector=? AND expires > NOW()");
    $stmt->bind_param("s", $selector);
    $stmt->execute();
    $result = $stmt->get_result();
    $row = $result->fetch_assoc();

    if ($row && hash_equals($row['hashed_token'], hash('sha256', hex2bin($token)))) {
        $_SESSION['user_id'] = $row['user_id'];

        // Regenerasi token agar tidak bisa digunakan ulang
        $newToken = random_bytes(33);
        $hashedNewToken = hash('sha256', $newToken);
        $stmt = $conn->prepare("UPDATE remember_tokens SET hashed_token=?, expires=DATE_ADD(NOW(), INTERVAL 30 DAY) WHERE id=?");
        $stmt->bind_param("si", $hashedNewToken, $row['id']);
        $stmt->execute();

        // Update cookie
        setcookie(
            'rememberme',
            $selector . ':' . bin2hex($newToken),
            time() + 86400 * 30,
            '/',
            '',
            true,
            true
        );
    } else {
        // Token invalid atau expired
        setcookie('rememberme', '', time() - 3600, '/');
    }
}
?>

Logout Spesifik per Perangkat

Pengguna bisa logout hanya dari perangkat yang sedang digunakan tanpa menghapus login di perangkat lain.

<?php
session_start();
include 'config.php';

if (isset($_SESSION['user_id'])) {
    if (isset($_COOKIE['rememberme'])) {
        list($selector,) = explode(':', $_COOKIE['rememberme']);
        $stmt = $conn->prepare("DELETE FROM remember_tokens WHERE selector=?");
        $stmt->bind_param("s", $selector);
        $stmt->execute();
        setcookie('rememberme', '', time() - 3600, '/');
    }

    session_unset();
    session_destroy();
}

header("Location: login.php?logout=1");
exit();
?>

Logout dari Semua Perangkat

Untuk keamanan lebih, admin atau pengguna bisa menambahkan tombol “Logout dari Semua Perangkat”, yang akan menghapus semua token untuk user tersebut.

<?php
session_start();
include 'config.php';

$user_id = $_SESSION['user_id'];
$stmt = $conn->prepare("DELETE FROM remember_tokens WHERE user_id=?");
$stmt->bind_param("i", $user_id);
$stmt->execute();

setcookie('rememberme', '', time() - 3600, '/');
session_unset();
session_destroy();

header("Location: login.php?logout_all=1");
exit();
?>

Keamanan Tambahan

Gunakan HTTPS
Agar cookie tidak bocor di jaringan publik.

Aktifkan HttpOnly dan Secure pada cookie
Mencegah akses cookie oleh JavaScript (anti XSS).

Hash token di database
Token asli hanya ada di cookie (client), bukan di database.

Batasi masa aktif token
Misalnya 30 hari, dan hapus token expired secara otomatis.

Catat user_agent & IP
Jika token digunakan dari perangkat atau lokasi berbeda, bisa dianggap mencurigakan.

Manajemen Perangkat Aktif (Opsional)

Kamu bisa membuat halaman “Perangkat yang Aktif” agar pengguna melihat dari mana saja akun mereka login.

Contoh query:

<?php
$user_id = $_SESSION['user_id'];
$result = $conn->query("SELECT device, ip_address, expires, created_at FROM remember_tokens WHERE user_id='$user_id'");
while ($row = $result->fetch_assoc()) {
    echo "<li>Device: {$row['device']} | IP: {$row['ip_address']} | Login: {$row['created_at']}</li>";
}
?>

Tambahkan tombol “Logout perangkat ini” untuk menghapus token berdasarkan selector tertentu.

Kesimpulan

Dengan sistem ini, kamu sudah membuat fitur Remember Me yang aman dan mendukung multi-device login di PHP.
Fitur ini memungkinkan pengguna login dari banyak perangkat sekaligus tanpa mengorbankan keamanan.

Keunggulan sistem ini:

  • Token unik untuk setiap perangkat

  • Hash dan validasi token di database

  • Auto login aman & logout per perangkat

  • Perlindungan dari session hijacking

Category: PHP