WebTech Interaktif XI RPL

Laravel · Bab 10

Lab 7: Autentikasi & Proteksi Rute

Membangun login dan logout berbasis session yang aman dari session fixation, lalu mengunci seluruh modul aplikasi dengan middleware auth.

Di lab ini Smart Retail App dikunci: hanya petugas kasir yang sudah login yang boleh membuka katalog dan transaksi. Kamu membangun controller autentikasi sendiri memakai facade Auth, lalu memasang middleware auth pada rute. Contoh kode memakai studi kasus perpustakaan; terapkan polanya ke Retail Store.

Alur Langkah

  1. Jalankan php artisan make:controller <NamaController> untuk controller autentikasi.
  2. Isi method showLogin() (tampilkan view login), login() (validasi email dan password, coba login, regenerasi session, arahkan ke katalog; bila gagal kembali dengan pesan galat), dan logout() (logout, hapus session, buat ulang token, arahkan ke halaman login).
  3. Buat folder resources/views/auth/, lalu buat login.blade.php berisi form email dan password (dengan @csrf, old('email'), dan @error).
  4. Susun ulang routes/web.php: rute login (GET, bernama login), proses login (POST), dan logout (POST) di luar kelompok; rute /, resource produk, dan tiga rute transaksi di dalam Route::middleware(['auth'])->group.
  5. Uji membuka katalog tanpa login, login dengan akun kasir dari seeder Lab 2, lalu Sign Out.

Login dengan Auth::attempt

use Illuminate\Support\Facades\Auth;

public function login(Request $request)
{
    $credentials = $request->validate([
        'email'    => 'required|email',
        'password' => 'required',
    ]);

    if (Auth::attempt($credentials)) {
        $request->session()->regenerate();
        return redirect()->intended(route('books.index'));
    }

    return back()->withErrors([
        'email' => 'Email atau kata sandi salah.',
    ])->onlyInput('email');
}
  • Auth::attempt mencari pengguna berdasarkan email, lalu membandingkan password dengan hash di database. Karena itu password di seeder wajib dibuat dengan Hash::make.
  • session()->regenerate() mengganti ID session setelah login. Tanpa ini, penyerang yang sudah menanamkan ID session tertentu di peramban korban bisa ikut masuk setelah korban login — serangan ini disebut Session Fixation.
  • redirect()->intended(...) mengembalikan pengguna ke halaman yang tadi ingin dibukanya sebelum dipaksa login, atau ke halaman bawaan.
  • withErrors([...]) mengirim pesan galat ke @error('email'), dan onlyInput('email') mengisi ulang email tanpa mengisi ulang password.

Logout yang Aman

public function logout(Request $request)
{
    Auth::logout();
    $request->session()->invalidate();
    $request->session()->regenerateToken();

    return redirect()->route('login');
}

invalidate() menghapus seluruh data session, dan regenerateToken() membuat token CSRF baru sehingga form lama tidak bisa dipakai ulang.

Proteksi Rute dengan Middleware

Middleware adalah pemeriksa yang berjalan sebelum controller. Middleware auth mengalihkan pengunjung yang belum login ke rute bernama login.

use App\Http\Controllers\BookController;
use App\Http\Controllers\LoginController;
use Illuminate\Support\Facades\Route;

Route::get('/login', [LoginController::class, 'showLogin'])->name('login');
Route::post('/login', [LoginController::class, 'login'])->name('login.post');
Route::post('/logout', [LoginController::class, 'logout'])->name('logout');

Route::middleware(['auth'])->group(function () {
    Route::get('/', function () {
        return redirect()->route('books.index');
    });

    Route::resource('books', BookController::class);
});

Rute login dan logout sengaja diletakkan di luar kelompok: halaman login harus bisa dibuka oleh orang yang belum login.

Menampilkan Status Login di Layout

Navbar layout dari Lab 3 memakai direktif @auth untuk menampilkan nama petugas dan tombol keluar. Pemeriksaan Route::has dari Lab 3 tetap dipertahankan:

@auth
    <span>Petugas: <strong>{{ Auth::user()->name }}</strong></span>
    @if(Route::has('logout'))
        <form action="{{ route('logout') }}" method="POST">
            @csrf
            <button type="submit" class="btn btn-outline-danger btn-sm">Sign Out</button>
        </form>
    @endif
@else
    @if(Route::has('login'))
        <a href="{{ route('login') }}" class="btn btn-outline-warning btn-sm">Sign In</a>
    @endif
@endauth

Logout wajib lewat form POST dengan @csrf agar tidak bisa dipicu oleh tautan dari situs lain. Akun untuk login adalah akun kasir yang dibuat seeder di Lab 2.

Hasil yang Diharapkan

Membuka katalog tanpa login langsung dialihkan ke halaman login. Setelah login dengan akun kasir, navbar menampilkan nama petugas dan semua modul bisa dipakai. Setelah Sign Out, katalog kembali terkunci.