# Validirati i filtrirati unos u PHP-u pomoću filter_var

> Validacija unosa u PHP-u pomoću filter_var i filter_input_array: brojevi, e-pošta, URL, bool, popisi dopuštenog i granice. S primjerima koda.

Izvor: https://phpsos.de/hr/blog/eingaben-validieren-php/  
Stanje: 25.10.2026  
Pružatelj: PHP SOS, PHP hitna pomoć i sigurnost poslužitelja. Hitna pomoć putem WhatsAppa: https://wa.me/491736494914?text=Pozdrav%20PHP%20SOS%2C%20trebamo%20pomo%C4%87%20s%20na%C5%A1im%20PHP%20poslu%C5%BEiteljem.%20Tvrtka%3A%20%E2%80%A6%20Web-stranica%3A%20%E2%80%A6

**Ukratko:** Unos u PHP-u validirate pomoću `filter_var()` ili `filter_input_array()` i jasnih pravila po polju: tip, raspon, duljina i dopuštene vrijednosti. Što ne odgovara, odbija se, a ne šutke preinačuje. Validacija je važna za čiste podatke i manju napadnu površinu, ali ne zamjenjuje ni Prepared Statements protiv SQL injectiona ni kodiranje prilagođeno kontekstu protiv XSS-a.

## Zašto „sve filtrirati“ nije koncept

U mnogim starijim PHP projektima na početku svake datoteke nalazi se petlja koja sve vrijednosti iz `$_GET` i `$_POST` šalje kroz funkciju za čišćenje. To djeluje sigurno. U praksi ponekad ukloni previše, primjerice apostrofe u prezimenima, a ponekad premalo, jer ista funkcija treba istodobno vrijediti za SQL, HTML i nazive datoteka.

Smislena validacija radi drugačije: za svako polje pita što je tamo dopušteno. Količina narudžbe je cijeli broj između 1 i gornje granice. Polje sortiranja jedna je od triju fiksnih vrijednosti. Datum postoji u određenom formatu i nakon nekog drugog datuma. Sve ostalo se odbija.

OWASP pritom razlikuje dvije razine: **sintaktičku** provjeru ima li vrijednost ispravan oblik i **semantičku** provjeru ima li smisla u kontekstu. Obje pripadaju na poslužitelj; provjere u pregledniku služe samo praktičnosti korištenja.

## Koje filtre PHP donosi

Proširenje Filter standardno je uključeno u PHP. Najvažniji filtri za validaciju prema PHP priručniku:

| Filtar | Provjerava | Važne opcije i napomene |
|---|---|---|
| `FILTER_VALIDATE_INT` | cijeli broj | `min_range`, `max_range` |
| `FILTER_VALIDATE_FLOAT` | decimalni broj | `decimal` za znak razdvajanja |
| `FILTER_VALIDATE_BOOL` | logička vrijednost | s `FILTER_NULL_ON_FAILURE` razlučiva od „false“ |
| `FILTER_VALIDATE_EMAIL` | oblik adrese e-pošte | ne dokazuje da poštanski sandučić postoji |
| `FILTER_VALIDATE_URL` | oblik URL-a | shemu provjeriti sami, bez internacionaliziranih domena |
| `FILTER_VALIDATE_IP` | IP adresa | zastavice za privatne i rezervirane raspone |
| `FILTER_VALIDATE_REGEXP` | vlastiti uzorak | uzorak usidriti s `^` i `$` |

Filtar za čišćenje `FILTER_SANITIZE_STRING` zastario je od PHP-a 8.1. Tko ga još koristi, trebao bi validaciju prebaciti na odgovarajuće filtre, a za izlaz koristiti `htmlspecialchars()`.

## filter_var u PHP-u: pravilno provjeriti obrazac

Pomoću `filter_input_array()` cijeli se obrazac može u jednom koraku provjeriti prema definiciji. Nepoznata polja se pritom ne preuzimaju:

```php
<?php
declare(strict_types=1);

$regeln = [
    'menge'   => ['filter' => FILTER_VALIDATE_INT,
                  'options' => ['min_range' => 1, 'max_range' => 50]],
    'email'   => FILTER_VALIDATE_EMAIL,
    'agb'     => ['filter' => FILTER_VALIDATE_BOOL, 'flags' => FILTER_NULL_ON_FAILURE],
    'versand' => ['filter' => FILTER_VALIDATE_REGEXP,
                  'options' => ['regexp' => '/^(standard|express)$/']],
];

$daten  = filter_input_array(INPUT_POST, $regeln) ?? [];
$fehler = [];

foreach ($regeln as $feld => $_) {
    if (!array_key_exists($feld, $daten) || $daten[$feld] === false || $daten[$feld] === null) {
        $fehler[] = $feld;
    }
}

if ($fehler !== []) {
    http_response_code(422);
    // ispisati poruku o pogrešci po polju, ne obrađivati unos
}
```

Obratite pažnju na stroge usporedbe pomoću `===`: valjana vrijednost `0` ili prazan string ne smiju se zamijeniti s neuspjehom. Zašto su ovdje opasne labave usporedbe, objašnjava članak [Type Juggling: labave usporedbe kao sigurnosni rizik](https://phpsos.de/hr/blog/type-juggling-php/). Kako PHP uopće stavlja na raspolaganje podatke zahtjeva, opisuje [Superglobals: $_GET, $_POST, $_FILES i ostali](https://phpsos.de/hr/php/superglobals/).

## Zamke kod e-pošte, URL-a i slobodnog teksta

Neki filtri rade manje nego što njihov naziv sugerira:

1. **URL-ovi:** `FILTER_VALIDATE_URL` prihvaća i druge sheme osim http i https. Shemu zatim provjerite pomoću `parse_url()` prema fiksnom popisu. Ako poslužitelj dohvaća URL, vrijede dodatna pravila, vidi [Spriječiti Server-Side Request Forgery u PHP-u](https://phpsos.de/hr/blog/ssrf-in-php/).
2. **Adrese e-pošte:** filtar provjerava oblik, a ne vlasništvo. Tko mora biti siguran, šalje poveznicu za potvrdu.
3. **Slobodni tekst:** imena, poruke i adrese teško se smisleno ograničavaju na znakove. Provjerite duljinu i kodiranje znakova, primjerice pomoću `mb_check_encoding($wert, 'UTF-8')`, a pri izlazu se oslonite na kodiranje.
4. **Regularni izrazi:** bez `^` i `$` uzorak provjerava samo pojavljuje li se negdje u tekstu, a ne odgovara li cijela vrijednost.
5. **Polja umjesto stringova:** napadač umjesto teksta može poslati polje (array). Bez provjere tipa to dovodi do upozorenja ili neočekivanog ponašanja.

> **Savjet:**
> Za fiksne vrijednosti odabira poput sortiranja, jezika ili načina dostave popis dopuštenog pomoću `in_array($wert, $erlaubt, true)` ili izraza `match` jednostavniji je i stroži od svakog regularnog izraza.

Još jedna česta pogreška tiče se brojeva sa značenjem, primjerice cijena, količina ili popusta. To što je vrijednost valjan broj ne govori ništa o tome je li u kontekstu dopuštena. Negativna količina, popust veći od vrijednosti robe ili cijena preuzeta iz obrasca umjesto iz baze podataka klasične su logičke pogreške. Cijene, ovlasti i statusne vrijednosti stoga uvijek pripadaju na poslužitelj, a nikad u skrivena polja obrasca.

## JSON, webhookovi i uvozi: validacija izvan obrazaca

Mnogi ulazi danas više nisu obrasci, nego JSON zahtjevi aplikacija, webhookovi pružatelja plaćanja ili uvozne datoteke dobavljača. I tamo vrijedi: najprije sigurno učitati, zatim provjeriti. OWASP savjetuje ograničiti veličinu i dubinu ugniježđenja prije nego se podaci uopće učitaju. U PHP-u `json_decode()` s maksimalnom dubinom i `JSON_THROW_ON_ERROR` preuzima dio toga:

```php
<?php
$roh = file_get_contents('php://input', false, null, 0, 65536); // najviše 64 KB
try {
    $daten = json_decode($roh, true, 16, JSON_THROW_ON_ERROR);
} catch (JsonException) {
    http_response_code(400);
    exit;
}
if (!is_array($daten) || !is_string($daten['bestellnummer'] ?? null)) {
    http_response_code(422);
    exit;
}
```

Kod webhookova prije provjere sadržaja stoji pitanje potječe li poruka doista od navedene usluge. Ako usluga nudi potpis, provjerite ga i usporedite pomoću `hash_equals()`. Kod uvoznih datoteka svaki redak provjerite kao obrazac i pri pogreškama uredno prekinite umjesto da preuzimate napola ispunjene zapise.

Poruke o pogreškama trebale bi navesti zahvaćeno polje, ali odbijenu vrijednost ne bi smjele vraćati nefiltriranu. Inače se na samoj poruci o pogrešci stvara novo mjesto izlaza koje se opet mora kodirati.

## Što validacija ne može učiniti

Validacija smanjuje napadnu površinu, ali prema OWASP-u nije glavna obrana protiv injectiona. Prezime s apostrofom je valjano i ipak mora sigurno dospjeti u bazu podataka. To uspijeva samo s Prepared Statements, kako pokazuje vodič [Spriječiti SQL injection u PHP-u](https://phpsos.de/hr/ratgeber/sql-injection-php/). A valjan tekst komentara postaje bezopasan tek kodiranjem prilagođenim kontekstu pri izlazu.

Ispravan redoslijed dakle glasi: pri primitku validirati, pri obradi parametrizirati, pri izlazu kodirati. Dodatno ispred toga idu ograničenja veličine: zahtjeve koji su preveliki web-poslužitelj i PHP uopće ne bi trebali obrađivati u cijelosti. Za to služe postavke poput `post_max_size`, koje se nakon PHP2Shella ionako trebaju provjeriti.

## Kako PHP SOS konkretno pomaže?

- Bilježimo sve ulaze Vaše aplikacije: obrasce, sučelja, uploade, uvoze i webhookove.
- Po polju utvrđujemo što je dopušteno i paušalne funkcije za čišćenje zamjenjujemo jasnim provjerama.
- Provjeravamo jesu li pristupi bazi podataka i izlazi osigurani neovisno o validaciji.
- Pravila dokumentiramo tako da ih Vaš tim može nastaviti kod novih funkcija.

Sustavnu provjeru opisuje usluga [Sigurnosni audit i penetracijski test](https://phpsos.de/hr/leistungen/sicherheitsaudit-penetrationstest/).


## Česta pitanja

**Koja je razlika između validiranja i čišćenja?**  
Validiranje provjerava odgovara li vrijednost očekivanjima i inače je odbija. Čišćenje mijenja vrijednost, primjerice uklanjanjem znakova. Za sigurnosne odluke odbijanje je gotovo uvijek bolje, jer šutke promijenjena vrijednost može stvoriti nove pogreške.

**Može li se FILTER_SANITIZE_STRING još koristiti?**  
Filtar je od PHP-a 8.1 označen kao zastarjeli. PHP priručnik umjesto toga preporučuje htmlspecialchars() pri izlazu. Postojeći kod trebali biste prilagoditi, jer zastarjele funkcije u budućim verzijama mogu nestati.

**Je li FILTER_VALIDATE_URL dovoljan da linkovi budu sigurni?**  
Ne. Filtar provjerava samo oblik adrese. Prema priručniku valjan URL ne mora počinjati s http, zato shemu morate sami provjeriti prema popisu dopuštenog, primjerice https. Internacionalizirane nazive domena filtar odbija.

**Moram li validirati i podatke iz vlastite baze podataka?**  
Pri izlazu se smatraju nepouzdanima i odgovarajuće se kodiraju. Ponovna validacija ima smisla kad su podaci izvorno došli izvana, a sada se koriste u novom kontekstu, primjerice kao naziv datoteke ili dio naredbe.

**Pomaže li validacija protiv PHP2Shella?**  
Ne. PHP2Shell pogađa obradu zahtjeva u PHP interpreteru, prije nego što Vaš aplikacijski kod uopće radi. Protiv toga pomaže samo PHP update s ponovnim pokretanjem svih PHP procesa.

## Izvori

- [PHP priručnik: konstante filtara](https://www.php.net/manual/de/filter.constants.php)
- [OWASP Input Validation Cheat Sheet](https://cheatsheetseries.owasp.org/cheatsheets/Input_Validation_Cheat_Sheet.html)
- [OWASP Top 10](https://owasp.org/www-project-top-ten/)
