Menguasai filter CodeIgniter: filter bawaan seperti csrf honeypot dan secureheaders, membuat custom filter before dan after, serta membangun rate limiting dengan Throttler untuk melindungi API dari brute force.

Di episode 12 kita memakai filter untuk proteksi login dan role, dan di episode 18 kita menyebutkan filter secureheaders bawaan. Sekarang saatnya membedah filter secara menyeluruh — mekanisme middleware CodeIgniter yang menjalankan logika sebelum dan sesudah request.
Mengapa penting? Karena filter adalah tempat yang tepat untuk kebutuhan lintas-halaman: autentikasi, rate limiting, security headers, CORS, dan logging. Tanpa filter, logika ini harus diulang di setiap controller — duplikasi yang pasti bocor. Di episode 19 ini kalian akan menguasai filter dan membangun rate limiter untuk melindungi API dan login dari brute force.
Filter adalah class yang mengimplementasikan FilterInterface dengan dua method:
<?php
namespace App\Filters;
use CodeIgniter\Filters\FilterInterface;
use CodeIgniter\HTTP\RequestInterface;
use CodeIgniter\HTTP\ResponseInterface;
class MyFilter implements FilterInterface
{
public function before(RequestInterface $request, $arguments = null): mixed
{
// Jalankan SEBELUM controller dieksekusi.
// Return null = lanjut; return redirect/response = hentikan.
}
public function after(RequestInterface $request, ResponseInterface $response, $arguments = null): ResponseInterface
{
// Jalankan SETELAH controller selesai.
return $response;
}
}Buat filter dengan perintah spark:
php spark make:filter ThrottleCodeIgniter 4 menyediakan filter siap pakai di app/Config/Filters.php:
public $aliases = [
'csrf' => \CodeIgniter\Filters\CSRF::class,
'toolbar' => \CodeIgniter\Filters\DebugToolbar::class,
'honeypot' => \CodeIgniter\Filters\Honeypot::class,
'invalidchars' => \CodeIgniter\Filters\InvalidChars::class,
'secureheaders' => \CodeIgniter\Filters\SecureHeaders::class,
'forcehttps' => \CodeIgniter\Filters\ForceHTTPS::class,
'auth' => \App\Filters\Auth::class,
];| Filter | Fungsi |
|---|---|
csrf | Proteksi CSRF semua request POST/PUT/DELETE |
honeypot | Trap bot spam form (hidden field) |
invalidchars | Blokir karakter tidak valid di request |
secureheaders | Pasang security headers standar |
forcehttps | Paksa HTTPS (dibahas episode 20) |
toolbar | Debug Toolbar (hanya development) |
Ada tiga level:
// 1. Global - semua request
public $globals = [
'before' => ['csrf', 'honeypot'],
'after' => ['toolbar'],
];
// 2. Per route - pakai alias
$routes->group('admin', ['filter' => 'auth:admin'], static function ($routes) {
$routes->get('users', 'Admin\Users::index');
});
// 3. Per route - inline class
$routes->get('upload', 'Upload::index', ['filter' => \App\Filters\Throttle::class]);Filter global bisa dikecualikan untuk sebagian route lewat except:
public $globals = [
'before' => [
'csrf' => ['except' => ['api/*']],
'honeypot',
],
];Note
Route API memakai except untuk CSRF karena digantikan token auth — kita akan pasang proteksi akses API lewat rate limiting dan API key di bawah. Jangan pernah mengecualikan CSRF untuk route form web tanpa pengganti yang sepadan.
Filter auth dari episode 12 dengan dukungan argumen role:
<?php
namespace App\Filters;
use CodeIgniter\Filters\FilterInterface;
use CodeIgniter\HTTP\RequestInterface;
use CodeIgniter\HTTP\ResponseInterface;
class Auth implements FilterInterface
{
public function before(RequestInterface $request, $arguments = null): mixed
{
if (! session()->get('logged_in')) {
return redirect()->to('/login')->with('error', 'Silakan login dulu.');
}
if ($arguments !== null && ! in_array(session()->get('role'), $arguments)) {
return redirect()->to('/')->with('error', 'Akses ditolak.');
}
return null;
}
public function after(RequestInterface $request, ResponseInterface $response, $arguments = null): ResponseInterface
{
return $response;
}
}before() mengembalikan null untuk lanjut, atau response/redirect untuk menghentikan request. Inilah inti kontrol alur CodeIgniter.
Rate limiting membatasi berapa banyak request yang boleh masuk dalam periode waktu tertentu — pertahanan utama melawan brute force dan penyalahgunaan API. CodeIgniter menyediakan class Throttler:
<?php
namespace App\Filters;
use CodeIgniter\Filters\FilterInterface;
use CodeIgniter\HTTP\RequestInterface;
use CodeIgniter\HTTP\ResponseInterface;
class Throttle implements FilterInterface
{
public function before(RequestInterface $request, $arguments = null): mixed
{
$throttler = \Config\Services::throttler();
$key = $request->getIPAddress(); // identitas: IP, token, atau user id
$capacity = 60; // maksimum request
$seconds = 60; // dalam rentang waktu ini
if (! $throttler->check($key, $capacity, $seconds)) {
return \Config\Services::response()
->setStatusCode(429)
->setJSON(['error' => 'Terlalu banyak request. Coba lagi nanti.']);
}
return null;
}
public function after(RequestInterface $request, ResponseInterface $response, $arguments = null): ResponseInterface
{
return $response;
}
}$throttler->check($key, $capacity, $seconds) mengembalikan true jika request masih dalam kuota. Jika melebihi, kita kembalikan status 429 Too Many Requests. Key identitas sebaiknya bukan hanya IP — di aplikasi nyata gabungkan dengan route/token agar limit lebih adil.
Tip
Throttler menyimpan state di cache handler (default file). Di produksi dengan banyak server, pastikan memakai Redis agar hitungan rate limit konsisten antar instance — detail di episode 24.
$routes->group('api/v1', ['namespace' => 'App\Controllers\Api\V1', 'filter' => 'throttle'], static function ($routes) {
$routes->resource('posts');
});Sekarang GET /api/v1/posts maksimal 60 request per menit per IP. Client yang melebihi kuota mendapat 429.
public $filters = [
'throttle' => [
'before' => [
'auth/login',
'password-reset/send',
],
],
];Dengan membatasi endpoint login, serangan brute force yang mencoba ribuan password dalam menit akan terhenti setelah beberapa percobaan.
for i in $(seq 1 65); do
code=$(curl -s -o /dev/null -w "%{http_code}" http://localhost:8080/api/v1/posts)
echo "Request $i: $code"
doneSetelah 60 request sukses (200), request berikutnya harus berstatus 429. Ini bukti nyata filter bekerja.
before() dan after().\Config\Services::throttler()) dengan check($key, $capacity, $seconds).Inti yang harus dibawa pulang:
except untuk mengecualikan CSRF di route API.Di episode 20 selanjutnya kita akan membahas HTTPS, headers & best practice — memaksa HTTPS, mengatur HSTS, cookie secure flags, dan konfigurasi web server Apache/Nginx untuk CodeIgniter 4. Aplikasi kalian siap menjadi warga internet yang baik!