PHP di Web: Form, Session & Keamanan
Siklus request/response, $_GET/$_POST, validasi input, escape output (XSS), password_hash, session, CSRF, dan unggah file aman.
PHP dan HTTP
Setiap kali browser membuka halaman, ia mengirim request (metode GET/POST, header, body) dan PHP membalas dengan response (status, header, body). PHP menyediakan data request lewat superglobal:
| Superglobal | Isi |
|---|---|
$_GET | Parameter di URL: ?q=laptop&hal=2 |
$_POST | Data form yang dikirim dengan metode POST |
$_SERVER | Metode request, path, IP, header (REQUEST_METHOD) |
$_COOKIE, $_SESSION | Cookie dan data sesi |
$_FILES | File yang diunggah |
Prinsip nomor satu: jangan percaya input
Semua yang datang dari pengguna — form, URL, header, cookie, file — bisa dipalsukan. Biasakan tiga langkah: validasi (apakah bentuknya benar?), sanitasi/cast (ubah ke tipe yang tepat), dan escape saat output (sesuai tujuan: HTML, SQL, shell).
$nama = trim((string) ($_POST['nama'] ?? ''));
$umur = filter_var($_POST['umur'] ?? null, FILTER_VALIDATE_INT, ['options' => ['min_range' => 1, 'max_range' => 120]]);
$email = filter_var($_POST['email'] ?? '', FILTER_VALIDATE_EMAIL);
$error = [];
if ($nama === '') { $error['nama'] = 'Nama wajib diisi'; }
if ($umur === false) { $error['umur'] = 'Umur tidak valid'; }
if ($email === false) { $error['email'] = 'Email tidak valid'; }
XSS — serangan lewat output
Jika kamu mencetak input pengguna mentah, penyerang bisa menyisipkan <script> yang berjalan di browser korban. Solusi: escape setiap kali mencetak ke HTML.
function e(string $teks): string
{
return htmlspecialchars($teks, ENT_QUOTES | ENT_SUBSTITUTE, 'UTF-8');
}
echo '<p>Halo, ' . e($nama) . '</p>';
SQL Injection — serangan lewat query
Menyusun SQL dengan menyambung string ("... WHERE email = '$email'") memungkinkan penyerang mengubah query. Selalu pakai prepared statement (dibahas di bab PDO).
Password: hash, jangan enkripsi
$hash = password_hash($passwordMentah, PASSWORD_DEFAULT); // simpan $hash di database
if (password_verify($passwordInput, $hash)) {
// login sukses
if (password_needs_rehash($hash, PASSWORD_DEFAULT)) { /* hash ulang & simpan */ }
}
Jangan pernah menyimpan password mentah, memakai md5()/sha1(), atau membuat algoritma sendiri. password_hash sudah menambahkan salt acak dan memakai algoritma kuat (bcrypt/argon2) yang sengaja lambat. Gunakan hash_equals() untuk membandingkan token secara aman.
Session & login
session_start([
'cookie_httponly' => true, // JS tidak bisa membaca cookie sesi
'cookie_secure' => true, // hanya lewat HTTPS
'cookie_samesite' => 'Lax',
'use_strict_mode' => true,
]);
// setelah login berhasil
session_regenerate_id(true); // cegah session fixation
$_SESSION['user_id'] = $user['id'];
// logout
$_SESSION = [];
session_destroy();
CSRF — formulir yang dipalsukan
Penyerang bisa membuat halaman yang diam-diam mengirim form ke situsmu memakai sesi korban. Lawan dengan token acak per sesi yang harus disertakan di setiap form:
// saat membuat form
$_SESSION['csrf'] ??= bin2hex(random_bytes(32));
echo '<input type="hidden" name="csrf" value="' . e($_SESSION['csrf']) . '">';
// saat memproses
if (!hash_equals($_SESSION['csrf'] ?? '', $_POST['csrf'] ?? '')) {
http_response_code(419);
exit('Token tidak valid');
}
Pola POST → Redirect → GET
Setelah memproses form, jangan langsung menampilkan halaman; arahkan ulang agar refresh tidak mengirim ulang data: header('Location: /sukses'); exit;
Unggah file dengan aman
- Cek
$_FILES['f']['error'] === UPLOAD_ERR_OKdan batasi ukuran. - Periksa tipe asli dengan
finfo(bukan ekstensi/$_FILES['type']yang bisa dipalsukan). - Buat nama baru yang acak; simpan di luar folder publik atau pastikan tidak bisa dieksekusi.
- Pindahkan dengan
move_uploaded_file().
Daftar periksa keamanan produksi
display_errors=Off,log_errors=On,expose_php=Off- HTTPS di mana-mana, header keamanan (CSP,
X-Content-Type-Options) - Rahasia (kunci API, password DB) di
.env/variabel lingkungan, bukan di kode - Perbarui PHP dan paket Composer secara rutin (
composer audit)