Membuat Sistem Login dengan CodeIgniter: Tutorial Lengkap dari Nol sampai Produksi

By | September 27, 2025

Membuat Sistem Login dengan CodeIgniter: Tutorial Lengkap dari Nol sampai Produksi

Pernah nggak sih kamu pengen bikin sistem login yang aman dan profesional untuk aplikasi web-mu? Tapi setiap kali coba, selalu ketemu masalah dengan security, session management, atau validasi yang ribet? Nah, dengan CodeIgniter, semua tantangan itu bisa diselesaikan dengan mudah dan elegan!

CodeIgniter adalah PHP framework yang ringan tapi powerful, perfect untuk bikin sistem autentikasi yang robust. Di tutorial ini, aku akan pandu kamu step-by-step membuat sistem login lengkap dengan register, login, logout, dan security features. Bahkan buat pemula sekalipun bisa ikutin!

Kita akan bangun dari nol sampe jadi sistem login production-ready. Siap-siap menguasai salah satu skill paling penting dalam web development!

Persiapan Environment Development

1. Install CodeIgniter 4

Pertama, pastikan kamu sudah punya environment PHP yang jalan. lalu install CodeIgniter 4 via Composer:

composer create-project codeigniter4/appstarter ci-login-system
cd ci-login-system

2. Konfigurasi Database

Edit file app/Config/Database.php:

public $default = [
    'DSN'      => '',
    'hostname' => 'localhost',
    'username' => 'root',
    'password' => '',
    'database' => 'ci_login_system',
    'DBDriver' => 'MySQLi',
    'DBPrefix' => '',
    'pConnect' => false,
    'DBDebug'  => true,
    'charset'  => 'utf8',
    'DBCollat' => 'utf8_general_ci',
    'swapPre'  => '',
    'encrypt'  => false,
    'compress' => false,
    'strictOn' => false,
    'failover' => [],
    'port'     => 3306,
];

3. Buat Database dan Table Users

Buat database dan table untuk menyimpan data user:

CREATE DATABASE ci_login_system;

CREATE TABLE users (
    id INT PRIMARY KEY AUTO_INCREMENT,
    name VARCHAR(100) NOT NULL,
    email VARCHAR(100) UNIQUE NOT NULL,
    password VARCHAR(255) NOT NULL,
    created_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP,
    updated_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP
);

Membuat Model User

Buat file app/Models/UserModel.php:

<?php

namespace App\Models;

use CodeIgniter\Model;

class UserModel extends Model
{
    protected $table = 'users';
    protected $primaryKey = 'id';
    protected $allowedFields = ['name', 'email', 'password'];
    protected $useTimestamps = true;
    protected $createdField = 'created_at';
    protected $updatedField = 'updated_at';

    // Validation rules
    protected $validationRules = [
        'name' => 'required|min_length[3]',
        'email' => 'required|valid_email|is_unique[users.email]',
        'password' => 'required|min_length[6]'
    ];

    protected $validationMessages = [
        'email' => [
            'is_unique' => 'Email sudah terdaftar.'
        ]
    ];

    // Hash password sebelum disimpan
    protected $beforeInsert = ['hashPassword'];
    protected $beforeUpdate = ['hashPassword'];

    protected function hashPassword(array $data)
    {
        if (!isset($data['data']['password'])) return $data;

        $data['data']['password'] = password_hash($data['data']['password'], PASSWORD_DEFAULT);
        return $data;
    }

    // Method untuk verifikasi login
    public function verifyLogin($email, $password)
    {
        $user = $this->where('email', $email)->first();

        if ($user && password_verify($password, $user['password'])) {
            return $user;
        }

        return false;
    }
}

Membuat Controller Auth

Buat file app/Controllers/AuthController.php:

<?php

namespace App\Controllers;

use App\Models\UserModel;
use CodeIgniter\Controller;

class AuthController extends Controller
{
    protected $userModel;
    protected $session;

    public function __construct()
    {
        $this->userModel = new UserModel();
        $this->session = \Config\Services::session();
        helper(['form', 'url']);
    }

    // Tampilkan form register
    public function register()
    {
        $data = [
            'title' => 'Register - CI Login System'
        ];
        return view('auth/register', $data);
    }

    // Proses registrasi
    public function processRegister()
    {
        // Validasi input
        $rules = [
            'name' => 'required|min_length[3]|max_length[100]',
            'email' => 'required|valid_email|is_unique[users.email]',
            'password' => 'required|min_length[6]|max_length[255]',
            'confirm_password' => 'required|matches[password]'
        ];

        if (!$this->validate($rules)) {
            return redirect()->back()->withInput()->with('errors', $this->validator->getErrors());
        }

        // Simpan user baru
        $userData = [
            'name' => $this->request->getPost('name'),
            'email' => $this->request->getPost('email'),
            'password' => $this->request->getPost('password')
        ];

        if ($this->userModel->save($userData)) {
            $this->session->setFlashdata('success', 'Registrasi berhasil! Silakan login.');
            return redirect()->to('/login');
        } else {
            return redirect()->back()->withInput()->with('errors', $this->userModel->errors());
        }
    }

    // Tampilkan form login
    public function login()
    {
        // Jika sudah login, redirect ke dashboard
        if ($this->session->get('isLoggedIn')) {
            return redirect()->to('/dashboard');
        }

        $data = [
            'title' => 'Login - CI Login System'
        ];
        return view('auth/login', $data);
    }

    // Proses login
    public function processLogin()
    {
        // Validasi input
        $rules = [
            'email' => 'required|valid_email',
            'password' => 'required'
        ];

        if (!$this->validate($rules)) {
            return redirect()->back()->withInput()->with('errors', $this->validator->getErrors());
        }

        $email = $this->request->getPost('email');
        $password = $this->request->getPost('password');

        // Verifikasi user
        $user = $this->userModel->verifyLogin($email, $password);

        if ($user) {
            // Set session
            $sessionData = [
                'userId' => $user['id'],
                'userName' => $user['name'],
                'userEmail' => $user['email'],
                'isLoggedIn' => true
            ];
            $this->session->set($sessionData);

            return redirect()->to('/dashboard');
        } else {
            return redirect()->back()->withInput()->with('error', 'Email atau password salah!');
        }
    }

    // Logout
    public function logout()
    {
        $this->session->destroy();
        return redirect()->to('/login');
    }
}

Membuat Dashboard Controller

Buat file app/Controllers/DashboardController.php:

<?php

namespace App\Controllers;

use CodeIgniter\Controller;

class DashboardController extends Controller
{
    protected $session;

    public function __construct()
    {
        $this->session = \Config\Services::session();
        
        // Cek apakah user sudah login
        if (!$this->session->get('isLoggedIn')) {
            return redirect()->to('/login');
        }
    }

    public function index()
    {
        $data = [
            'title' => 'Dashboard - CI Login System',
            'userName' => $this->session->get('userName'),
            'userEmail' => $this->session->get('userEmail')
        ];
        return view('dashboard/index', $data);
    }

    public function profile()
    {
        $data = [
            'title' => 'Profile - CI Login System',
            'userName' => $this->session->get('userName'),
            'userEmail' => $this->session->get('userEmail')
        ];
        return view('dashboard/profile', $data);
    }
}

Membuat Views (Tampilan)

1. Layout Template

Buat file app/Views/templates/header.php:

<!DOCTYPE html>
<html lang="id">
<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title><?= $title ?? 'CI Login System' ?></title>
    <link href="https://cdn.jsdelivr.net/npm/bootstrap@5.1.3/dist/css/bootstrap.min.css" rel="stylesheet">
    <style>
        .auth-container {
            max-width: 400px;
            margin: 100px auto;
            padding: 20px;
        }
    </style>
</head>
<body>
    <div class="container">

Buat file app/Views/templates/footer.php:

    </div>
    <script src="https://cdn.jsdelivr.net/npm/bootstrap@5.1.3/dist/js/bootstrap.bundle.min.js"></script>
</body>
</html>

2. View Register

Buat file app/Views/auth/register.php:

<?= $this->include('templates/header') ?>

<div class="auth-container">
    <h2 class="text-center mb-4">Daftar Akun Baru</h2>
    
    <?php if (session()->getFlashdata('success')): ?>
        <div class="alert alert-success"><?= session()->getFlashdata('success') ?></div>
    <?php endif; ?>

    <?php if (session()->getFlashdata('errors')): ?>
        <div class="alert alert-danger">
            <ul class="mb-0">
                <?php foreach (session()->getFlashdata('errors') as $error): ?>
                    <li><?= $error ?></li>
                <?php endforeach; ?>
            </ul>
        </div>
    <?php endif; ?>

    <form action="/register" method="POST">
        <?= csrf_field() ?>
        
        <div class="mb-3">
            <label for="name" class="form-label">Nama Lengkap</label>
            <input type="text" class="form-control" id="name" name="name" 
                   value="<?= old('name') ?>" required>
        </div>

        <div class="mb-3">
            <label for="email" class="form-label">Email</label>
            <input type="email" class="form-control" id="email" name="email" 
                   value="<?= old('email') ?>" required>
        </div>

        <div class="mb-3">
            <label for="password" class="form-label">Password</label>
            <input type="password" class="form-control" id="password" name="password" required>
        </div>

        <div class="mb-3">
            <label for="confirm_password" class="form-label">Konfirmasi Password</label>
            <input type="password" class="form-control" id="confirm_password" 
                   name="confirm_password" required>
        </div>

        <button type="submit" class="btn btn-primary w-100">Daftar</button>
    </form>

    <div class="text-center mt-3">
        <a href="/login">Sudah punya akun? Login di sini</a>
    </div>
</div>

<?= $this->include('templates/footer') ?>

3. View Login

Buat file app/Views/auth/login.php:

<?= $this->include('templates/header') ?>

<div class="auth-container">
    <h2 class="text-center mb-4">Login ke Akun Anda</h2>
    
    <?php if (session()->getFlashdata('success')): ?>
        <div class="alert alert-success"><?= session()->getFlashdata('success') ?></div>
    <?php endif; ?>

    <?php if (session()->getFlashdata('error')): ?>
        <div class="alert alert-danger"><?= session()->getFlashdata('error') ?></div>
    <?php endif; ?>

    <?php if (session()->getFlashdata('errors')): ?>
        <div class="alert alert-danger">
            <ul class="mb-0">
                <?php foreach (session()->getFlashdata('errors') as $error): ?>
                    <li><?= $error ?></li>
                <?php endforeach; ?>
            </ul>
        </div>
    <?php endif; ?>

    <form action="/login" method="POST">
        <?= csrf_field() ?>
        
        <div class="mb-3">
            <label for="email" class="form-label">Email</label>
            <input type="email" class="form-control" id="email" name="email" 
                   value="<?= old('email') ?>" required>
        </div>

        <div class="mb-3">
            <label for="password" class="form-label">Password</label>
            <input type="password" class="form-control" id="password" name="password" required>
        </div>

        <button type="submit" class="btn btn-primary w-100">Login</button>
    </form>

    <div class="text-center mt-3">
        <a href="/register">Belum punya akun? Daftar di sini</a>
    </div>
</div>

<?= $this->include('templates/footer') ?>

4. View Dashboard

Buat file app/Views/dashboard/index.php:

<?= $this->include('templates/header') ?>

<nav class="navbar navbar-expand-lg navbar-dark bg-dark">
    <div class="container">
        <a class="navbar-brand" href="#">CI Login System</a>
        <div class="navbar-nav ms-auto">
            <span class="navbar-text me-3">Halo, <?= $userName ?>!</span>
            <a class="nav-link" href="/profile">Profile</a>
            <a class="nav-link" href="/logout">Logout</a>
        </div>
    </div>
</nav>

<div class="container mt-4">
    <div class="row">
        <div class="col-md-12">
            <div class="card">
                <div class="card-header">
                    <h4>Dashboard</h4>
                </div>
                <div class="card-body">
                    <h5>Selamat datang di dashboard!</h5>
                    <p>Anda berhasil login sebagai <strong><?= $userName ?></strong> (<?= $userEmail ?>)</p>
                    <div class="alert alert-info">
                        <strong>Fitur yang tersedia:</strong>
                        <ul>
                            <li>Sistem login yang aman</li>
                            <li>Manajemen session</li>
                            <li>Password hashing</li>
                            <li>CSRF protection</li>
                        </ul>
                    </div>
                </div>
            </div>
        </div>
    </div>
</div>

<?= $this->include('templates/footer') ?>

Konfigurasi Routes

Edit file app/Config/Routes.php:

<?php

use App\Controllers\AuthController;
use App\Controllers\DashboardController;
use CodeIgniter\Router\RouteCollection;

/**
 * @var RouteCollection $routes
 */

// Auth Routes
$routes->get('register', [AuthController::class, 'register']);
$routes->post('register', [AuthController::class, 'processRegister']);
$routes->get('login', [AuthController::class, 'login']);
$routes->post('login', [AuthController::class, 'processLogin']);
$routes->get('logout', [AuthController::class, 'logout']);

// Dashboard Routes (protected)
$routes->get('dashboard', [DashboardController::class, 'index']);
$routes->get('profile', [DashboardController::class, 'profile']);

// Default route
$routes->get('/', function() {
    return redirect()->to('/login');
});

Security Features yang Sudah Diimplementasi

1. Password Hashing

Password disimpan dengan password_hash() dan diverifikasi dengan password_verify().

2. CSRF Protection

Menggunakan csrf_field() untuk mencegah Cross-Site Request Forgery.

3. Input Validation

Validasi input di server-side untuk mencegah malicious data.

4. Session Management

Session dikelola dengan aman oleh CodeIgniter Session library.

5. SQL Injection Prevention

Menggunakan Query Builder CodeIgniter yang sudah aman dari SQL injection.

Testing Sistem Login

Test semua functionality yang sudah dibuat:

  1. Buka http://localhost:8080/register – Test registrasi user baru
  2. Buka http://localhost:8080/login – Test login dengan user yang sudah terdaftar
  3. Akses http://localhost:8080/dashboard – Pastikan hanya accessible setelah login
  4. Test logout functionality
  5. Coba akses dashboard tanpa login – Harus redirect ke login page

Enhancement yang Bisa Ditambahkan

1. Remember Me Functionality

// Tambahkan remember token di table users
// Implementasi cookies untuk persistent login

2. Email Verification

// Kirim email verifikasi setelah registrasi
// Validasi email sebelum bisa login

3. Password Reset

// Fitur lupa password dengan token reset
// Kirim link reset via email

4. Role-based Access Control

// Tambahkan kolom role di table users
// Implementasi permissions untuk different user levels

Kesimpulan: Sistem Login Production-Ready

Dengan mengikuti tutorial CodeIgniter ini, kamu sudah berhasil membuat sistem login yang aman dan profesional. Sistem ini sudah termasuk:

  • Registrasi user dengan validasi
  • Login dengan password hashing
  • Session management yang proper
  • Security features lengkap
  • Dashboard protected area

Yang perlu diingat:

  • Security First: Selalu prioritaskan keamanan dalam autentikasi
  • Validation: Jangan percaya input user, selalu validasi
  • Error Handling: Handle errors dengan graceful
  • User Experience: Berikan feedback yang jelas ke user

Sistem ini bisa dikembangkan lebih lanjut sesuai kebutuhan project-mu. Selamat mencoba dan happy coding!