# Validácia a filtrovanie vstupov v PHP pomocou filter_var

> Validácia vstupov v PHP pomocou filter_var a filter_input_array: čísla, e-mail, URL, bool, zoznamy povolených hodnôt a hranice. S ukážkami kódu.

Zdroj: https://phpsos.de/sk/blog/eingaben-validieren-php/  
Stav: 25.10.2026  
Poskytovateľ: PHP SOS, Núdzová pomoc pri PHP a bezpečnosť serverov. Okamžitá pomoc cez WhatsApp: https://wa.me/491736494914?text=Dobr%C3%BD%20de%C5%88%2C%20PHP%20SOS%2C%20potrebujeme%20pomoc%20s%20na%C5%A1%C3%ADm%20serverom%20s%20PHP.%20Spolo%C4%8Dnos%C5%A5%3A%20%E2%80%A6%20Web%3A%20%E2%80%A6

**Stručne:** Vstupy v PHP validujete pomocou `filter_var()` alebo `filter_input_array()` a jasných pravidiel pre každé pole: typ, rozsah, dĺžka a povolené hodnoty. Čo nesedí, sa odmietne, nie mlčky prerobí. Validácia je dôležitá pre čisté údaje a menšiu útočnú plochu, nenahrádza však ani Prepared Statements proti SQL injection, ani kódovanie primerané kontextu proti XSS.

## Prečo „filtrovať všetko“ nie je koncepcia

V mnohých starších projektoch PHP nájdete na začiatku každého súboru cyklus, ktorý posiela všetky hodnoty z `$_GET` a `$_POST` cez čistiacu funkciu. Pôsobí to bezpečne. V praxi to raz odstráni priveľa, napríklad apostrofy v priezviskách, raz primálo, pretože tá istá funkcia má platiť naraz pre SQL, HTML a názvy súborov.

Zmysluplná validácia funguje inak: pre každé pole sa pýta, čo je tam dovolené. Objednané množstvo je celé číslo od 1 po hornú hranicu. Pole zoradenia je jedna z troch pevných hodnôt. Dátum má určitý formát a leží pred iným dátumom alebo po ňom. Všetko ostatné sa odmietne.

OWASP pritom rozlišuje dve úrovne: **syntaktickú** kontrolu, či má hodnota správny tvar, a **sémantickú** kontrolu, či dáva v súvislosti zmysel. Obe patria na server; kontroly v prehliadači slúžia len na pohodlné ovládanie.

## Ktoré filtre PHP prináša

Rozšírenie Filter je v PHP štandardne obsiahnuté. Najdôležitejšie validačné filtre podľa príručky PHP:

| Filter | Kontroluje | Dôležité možnosti a poznámky |
|---|---|---|
| `FILTER_VALIDATE_INT` | celé číslo | `min_range`, `max_range` |
| `FILTER_VALIDATE_FLOAT` | desatinné číslo | `decimal` pre oddeľovač |
| `FILTER_VALIDATE_BOOL` | pravdivostná hodnota | s `FILTER_NULL_ON_FAILURE` rozlíšiteľná od „nepravda“ |
| `FILTER_VALIDATE_EMAIL` | tvar e-mailovej adresy | nedokazuje, že schránka existuje |
| `FILTER_VALIDATE_URL` | tvar URL | schému kontrolovať samostatne, žiadne internacionalizované domény |
| `FILTER_VALIDATE_IP` | adresa IP | príznaky pre súkromné a rezervované rozsahy |
| `FILTER_VALIDATE_REGEXP` | vlastný vzor | vzor ukotviť pomocou `^` a `$` |

Čistiaci filter `FILTER_SANITIZE_STRING` je od PHP 8.1 zastaraný. Kto ho ešte používa, mal by validáciu prestaviť na vhodné filtre a pre výstup použiť `htmlspecialchars()`.

## filter_var v PHP: poriadna kontrola formulára

Pomocou `filter_input_array()` sa dá celý formulár skontrolovať jedným krokom voči definícii. Neznáme polia sa pritom neprevezmú:

```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);
    // vypísať chybové hlásenie pre každé pole, vstupy nespracovať
}
```

Všimnite si striktné porovnania pomocou `===`: platná hodnota `0` alebo prázdny reťazec sa nesmie zamieňať s neúspechom. Prečo sú tu voľné porovnania nebezpečné, vysvetľuje [Type Juggling: voľné porovnania ako bezpečnostné riziko](https://phpsos.de/sk/blog/type-juggling-php/). Ako PHP vôbec sprístupňuje údaje požiadavky, opisuje [Superglobals: $_GET, $_POST, $_FILES a spol.](https://phpsos.de/sk/php/superglobals/).

## Nástrahy pri e-maile, URL a voľných textoch

Niektoré filtre robia menej, než by naznačoval ich názov:

1. **URL:** `FILTER_VALIDATE_URL` akceptuje aj iné schémy než http a https. Schému potom skontrolujte pomocou `parse_url()` voči pevnému zoznamu. Ak sa URL sťahuje zo servera, platia dodatočné pravidlá, pozri [Ako zabrániť Server-Side Request Forgery v PHP](https://phpsos.de/sk/blog/ssrf-in-php/).
2. **E-mailové adresy:** filter kontroluje tvar, nie vlastníctvo. Kto si musí byť istý, pošle potvrdzovací odkaz.
3. **Voľný text:** mená, správy a adresy sa dajú len ťažko zmysluplne obmedziť na znaky. Kontrolujte dĺžku a kódovanie znakov, napríklad pomocou `mb_check_encoding($wert, 'UTF-8')`, a pri výstupe sa spoliehajte na kódovanie.
4. **Regulárne výrazy:** bez `^` a `$` vzor kontroluje len to, či sa niekde v texte vyskytuje, nie či sedí celá hodnota.
5. **Polia namiesto reťazcov:** útočník môže namiesto textu poslať pole. Bez kontroly typu to vedie k upozorneniam alebo neočakávanému správaniu.

> **Tip:**
> Pre pevné hodnoty výberu, ako zoradenie, jazyk alebo spôsob dopravy, je zoznam povolených hodnôt pomocou `in_array($wert, $erlaubt, true)` alebo výrazu `match` jednoduchší a prísnejší než ktorýkoľvek regulárny výraz.

Ďalšia častá chyba sa týka čísel s významom, napríklad cien, množstiev alebo zliav. To, že hodnota je platné číslo, nehovorí nič o tom, či je v danej súvislosti dovolená. Záporné množstvo, zľava vyššia než hodnota tovaru alebo cena prevzatá z formulára namiesto z databázy sú klasické logické chyby. Ceny, oprávnenia a stavové hodnoty preto vždy patria na server a nikdy do skrytých polí formulára.

## JSON, webhooky a importy: validácia mimo formulárov

Mnohé vstupy dnes už nie sú formuláre, ale požiadavky JSON z aplikácií, webhooky od platobných služieb alebo importné súbory od dodávateľov. Aj tu platí: najprv bezpečne načítať, potom skontrolovať. OWASP radí obmedziť veľkosť a hĺbku vnorenia ešte pred načítaním údajov. V PHP časť z toho preberá `json_decode()` s maximálnou hĺbkou a `JSON_THROW_ON_ERROR`:

```php
<?php
$roh = file_get_contents('php://input', false, null, 0, 65536); // najviac 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;
}
```

Pri webhookoch stojí pred obsahovou kontrolou otázka, či správa skutočne pochádza z uvedenej služby. Ak služba ponúka podpis, skontrolujte ho a porovnajte pomocou `hash_equals()`. Pri importných súboroch skontrolujte každý riadok ako formulár a pri chybách čisto prerušte, namiesto preberania polovičných záznamov.

Chybové hlásenia by mali uvádzať dotknuté pole, odmietnutú hodnotu by však nemali vracať nefiltrovanú. Inak vznikne na chybovom hlásení samotnom nové miesto výstupu, ktoré sa musí opäť kódovať.

## Čo validácia nedokáže

Validácia zmenšuje útočnú plochu, ale podľa OWASP nie je hlavnou obranou proti injection. Priezvisko s apostrofom je platné a napriek tomu sa musí bezpečne dostať do databázy. To sa podarí len pomocou Prepared Statements, ako ukazuje sprievodca [Ako zabrániť SQL injection v PHP](https://phpsos.de/sk/ratgeber/sql-injection-php/). A platný text komentára sa stane neškodným až kódovaním primeraným kontextu pri výstupe.

Správne poradie teda znie: pri prijatí validovať, pri spracovaní parametrizovať, pri výstupe kódovať. Pred to patria aj limity veľkosti: požiadavky, ktoré sú oveľa príliš veľké, by webserver a PHP nemali ani spracovať celé. Slúžia na to nastavenia ako `post_max_size`, ktoré by sa mali po PHP2Shell tak či tak skontrolovať.

## Ako konkrétne pomáha PHP SOS?

- Zachytíme všetky vstupy vašej aplikácie: formuláre, rozhrania, uploady, importy a webhooky.
- Pre každé pole určíme, čo je dovolené, a plošné čistiace funkcie nahradíme jasnými kontrolami.
- Preveríme, či sú prístupy do databázy a výstupy zabezpečené nezávisle od validácie.
- Pravidlá zdokumentujeme tak, aby ich váš tím mohol pri nových funkciách dodržiavať ďalej.

Systematickú kontrolu opisuje služba [Bezpečnostný audit a penetračný test](https://phpsos.de/sk/leistungen/sicherheitsaudit-penetrationstest/).


## Časté otázky

**Aký je rozdiel medzi validáciou a čistením?**  
Validácia kontroluje, či hodnota zodpovedá očakávaniam, a ak nie, odmietne ju. Čistenie hodnotu mení, napríklad odstránením znakov. Pre bezpečnostné rozhodnutia je takmer vždy lepšie odmietnuť, pretože mlčky zmenená hodnota môže vyvolať nové chyby.

**Dá sa FILTER_SANITIZE_STRING ešte používať?**  
Filter je od PHP 8.1 označený ako zastaraný. Príručka PHP namiesto toho odporúča htmlspecialchars() pri výstupe. Existujúci kód by ste mali prestaviť, pretože zastarané funkcie môžu v budúcich verziách zaniknúť.

**Stačí FILTER_VALIDATE_URL na zabezpečenie odkazov?**  
Nie. Filter kontroluje len tvar adresy. Podľa príručky nemusí platná URL začínať http, preto musíte schému sami skontrolovať voči zoznamu povolených hodnôt, ako je https. Internacionalizované názvy domén filter odmieta.

**Musím validovať aj údaje z vlastnej databázy?**  
Pri výstupe sa považujú za nedôveryhodné a primerane sa kódujú. Opätovná validácia má zmysel, ak údaje pôvodne prišli zvonka a teraz sa používajú v novej súvislosti, napríklad ako názov súboru alebo časť príkazu.

**Pomáha validácia proti PHP2Shell?**  
Nie. PHP2Shell sa týka spracovania požiadaviek v interpreteri PHP skôr, než vôbec začne bežať kód vašej aplikácie. Proti tomu pomáha len aktualizácia PHP s následným reštartom všetkých procesov PHP.

## Zdroje

- [Príručka PHP: konštanty filtrov](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/)
