Otorisasi: Gate & Policy
Mengatur siapa boleh melakukan apa dengan Policy, Gate, @can, dan atribut #[Authorize] di Laravel 13.
Autentikasi vs otorisasi
Autentikasi menjawab "kamu siapa?". Otorisasi menjawab "kamu boleh melakukan ini?". Contoh: semua pengguna yang login boleh melihat produk, tetapi hanya pemilik atau admin yang boleh mengubahnya.
Dua alat: Gate dan Policy
- Gate — closure sederhana untuk aksi umum yang tidak terikat model (
akses-laporan). - Policy — class yang mengelompokkan aturan otorisasi untuk satu model (
ProdukPolicy). Pilihan utama untuk CRUD.
Membuat policy
php artisan make:policy ProdukPolicy --model=Produk
<?php
namespace App\Policies;
use App\Models\Produk;
use App\Models\User;
class ProdukPolicy
{
public function viewAny(User $user): bool
{
return true;
}
public function update(User $user, Produk $produk): bool
{
return $user->id === $produk->user_id || $user->is_admin;
}
public function delete(User $user, Produk $produk): bool
{
return $user->is_admin;
}
}
Setiap method menerima pengguna yang sedang login (otomatis) dan, jika perlu, model, lalu mengembalikan true (boleh) atau false (dilarang → 403). Laravel menemukan policy secara otomatis dengan konvensi nama (Produk → ProdukPolicy) — tanpa registrasi manual.
Memakai policy
use Illuminate\Support\Facades\Gate;
public function update(Request $request, Produk $produk)
{
Gate::authorize('update', $produk); // lempar 403 bila tidak diizinkan
// ...lanjut mengubah...
}
if (Gate::allows('delete', $produk)) { ... } // cek tanpa exception
if ($request->user()->can('update', $produk)) { ... }
if ($request->user()->cannot('update', $produk)) { abort(403); }
Di Blade
@can('update', $produk)
<a href="{{ route('produk.edit', $produk) }}">Ubah</a>
@endcan
@cannot('delete', $produk) ... @endcannot
Menyembunyikan tombol bukan pengamanan! Selalu tegakkan aturan di sisi server (controller/policy); @can hanya merapikan tampilan.
Di route (middleware can)
Route::put('/produk/{produk}', [ProdukController::class, 'update'])->can('update', 'produk');
Atribut #[Authorize] — gaya Laravel 13
Otorisasi dapat dideklarasikan langsung pada method controller:
use Illuminate\Routing\Attributes\Controllers\Authorize;
#[Authorize('create', [Komentar::class, 'post'])]
public function store(Post $post)
{
// ...
}
Gate sederhana
// AppServiceProvider::boot()
Gate::define('akses-laporan', fn (User $user) => $user->is_admin);
Gate::allows('akses-laporan');
@can('akses-laporan') ... @endcan
Role & permission yang rumit
Untuk peran dan izin dinamis (admin, editor, kasir, dapat diatur lewat UI), banyak proyek memakai paket spatie/laravel-permission; policy tetap dipakai untuk aturan berbasis kepemilikan.
Praktik baik
- Prinsip least privilege: default tolak, izinkan seperlunya.
- Satu policy per model; method mengikuti nama aksi resource (
viewAny, view, create, update, delete, restore, forceDelete). - Tes policy secara terpisah (mudah karena hanya fungsi murni).