# Validera och filtrera inmatning i PHP med filter_var

> Validera inmatning i PHP med filter_var och filter_input_array: tal, e-post, URL, bool, tillåtelselistor och gränser. Med kodexempel och fallgropar.

Källa: https://phpsos.de/sv/blog/eingaben-validieren-php/  
Aktualitet: 2026-10-25  
Leverantör: PHP SOS, PHP-nödhjälp och serversäkerhet. Omedelbar hjälp via WhatsApp: https://wa.me/491736494914?text=Hej%20PHP%20SOS%2C%20vi%20beh%C3%B6ver%20hj%C3%A4lp%20med%20v%C3%A5r%20PHP-server.%20F%C3%B6retag%3A%20%E2%80%A6%20Webbplats%3A%20%E2%80%A6

**Kort sagt:** Inmatning i PHP validerar ni med `filter_var()` eller `filter_input_array()` och tydliga regler per fält: typ, intervall, längd och tillåtna värden. Det som inte passar avvisas, det byggs inte tyst om. Validering är viktig för rena data och mindre angreppsyta men ersätter varken prepared statements mot SQL-injektion eller kontextanpassad kodning mot XSS.

## Varför ”filtrera allt” inte är något koncept

I många äldre PHP-projekt finns i början av varje fil en loop som skickar alla värden från `$_GET` och `$_POST` genom en saneringsfunktion. Det känns säkert. I praktiken tar den ibland bort för mycket, till exempel apostrofer i efternamn, och ibland för lite, eftersom samma funktion ska gälla för SQL, HTML och filnamn samtidigt.

Meningsfull validering fungerar annorlunda: Den frågar för varje fält vad som är tillåtet. En beställd mängd är ett heltal mellan 1 och en övre gräns. Ett sorteringsfält är ett av tre fasta värden. Ett datum föreligger i ett bestämt format och ligger efter ett annat datum. Allt annat avvisas.

OWASP skiljer här mellan två nivåer: den **syntaktiska** kontrollen av om ett värde har rätt form och den **semantiska** kontrollen av om det är rimligt i sammanhanget. Båda hör hemma på servern; kontroller i webbläsaren tjänar bara användbarheten.

## Vilka filter PHP har med sig

Filtertillägget ingår i PHP som standard. De viktigaste valideringsfiltren enligt PHP-manualen:

| Filter | Kontrollerar | Viktiga alternativ och anmärkningar |
|---|---|---|
| `FILTER_VALIDATE_INT` | heltal | `min_range`, `max_range` |
| `FILTER_VALIDATE_FLOAT` | decimaltal | `decimal` för skiljetecknet |
| `FILTER_VALIDATE_BOOL` | sanningsvärde | med `FILTER_NULL_ON_FAILURE` skiljbart från ”falskt” |
| `FILTER_VALIDATE_EMAIL` | formen på en e-postadress | bevisar inte att postlådan finns |
| `FILTER_VALIDATE_URL` | formen på en URL | kontrollera schemat själv, inga internationaliserade domäner |
| `FILTER_VALIDATE_IP` | IP-adress | flaggor för privata och reserverade områden |
| `FILTER_VALIDATE_REGEXP` | eget mönster | förankra mönstret med `^` och `$` |

Saneringsfiltret `FILTER_SANITIZE_STRING` är föråldrat sedan PHP 8.1. Den som fortfarande använder det bör ställa om valideringen till lämpliga filter och använda `htmlspecialchars()` vid utmatning.

## filter_var i PHP: kontrollera ett formulär rent

Med `filter_input_array()` går det att kontrollera ett helt formulär i ett steg mot en definition. Okända fält tas då inte med:

```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);
    // Skriv ut felmeddelande per fält, bearbeta inte inmatningen
}
```

Observera de strikta jämförelserna med `===`: Ett giltigt värde `0` eller en tom sträng får inte förväxlas med ett misslyckande. Varför lösa jämförelser är farliga här förklarar [Type juggling: lösa jämförelser som säkerhetsrisk](https://phpsos.de/sv/blog/type-juggling-php/). Hur PHP över huvud taget tillhandahåller förfrågningsdata beskriver [Superglobals: $_GET, $_POST, $_FILES med flera](https://phpsos.de/sv/php/superglobals/).

## Fallgropar med e-post, URL och fri text

Vissa filter gör mindre än namnet låter påskina:

1. **URL:er:** `FILTER_VALIDATE_URL` accepterar även andra scheman än http och https. Kontrollera schemat därefter med `parse_url()` mot en fast lista. Hämtas URL:en av servern gäller ytterligare regler, se [Förhindra Server-Side Request Forgery i PHP](https://phpsos.de/sv/blog/ssrf-in-php/).
2. **E-postadresser:** Filtret kontrollerar formen, inte ägandet. Den som måste vara säker skickar en bekräftelselänk.
3. **Fri text:** Namn, meddelanden och adresser går knappast att begränsa meningsfullt till vissa tecken. Kontrollera längd och teckenkodning, till exempel med `mb_check_encoding($wert, 'UTF-8')`, och förlita er vid utmatning på kodning.
4. **Reguljära uttryck:** Utan `^` och `$` kontrollerar ett mönster bara om det förekommer någonstans i texten, inte om hela värdet passar.
5. **Arrayer i stället för strängar:** En angripare kan skicka en array i stället för en text. Utan typkontroll leder det till varningar eller oväntat beteende.

> **Tips:**
> För fasta urvalsvärden som sortering, språk eller fraktsätt är en tillåtelselista med `in_array($wert, $erlaubt, true)` eller ett `match`-uttryck enklare och strängare än varje reguljärt uttryck.

Ett ytterligare vanligt fel gäller tal med betydelse, till exempel priser, mängder eller rabatter. Att ett värde är ett giltigt tal säger ingenting om huruvida det är tillåtet i sammanhanget. En negativ mängd, en rabatt över varuvärdet eller ett pris som hämtas från formuläret i stället för från databasen är klassiska logikfel. Priser, behörigheter och statusvärden hör därför alltid hemma på servern och aldrig i dolda formulärfält.

## JSON, webhooks och importer: validering bortom formulär

Många ingångar är i dag inte längre formulär utan JSON-förfrågningar från appar, webhooks från betaltjänster eller importfiler från leverantörer. Även där gäller: läs först in säkert, kontrollera sedan. OWASP råder att begränsa storlek och nästlingsdjup innan data över huvud taget läses in. I PHP tar `json_decode()` med ett maximalt djup och `JSON_THROW_ON_ERROR` hand om en del av det:

```php
<?php
$roh = file_get_contents('php://input', false, null, 0, 65536); // högst 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;
}
```

Vid webhooks kommer före den innehållsliga kontrollen frågan om meddelandet verkligen kommer från den angivna tjänsten. Erbjuder tjänsten en signatur kontrollerar ni den och jämför med `hash_equals()`. Vid importfiler kontrollerar ni varje rad som ett formulär och avbryter rent vid fel i stället för att ta över halva datapost.

Felmeddelanden bör ange det berörda fältet men inte returnera det avvisade värdet ofiltrerat. Annars uppstår en ny utmatningsplats i själva felmeddelandet, som återigen måste kodas.

## Vad validering inte kan åstadkomma

Validering minskar angreppsytan, men den är enligt OWASP inte det främsta försvaret mot injektion. Ett efternamn med apostrof är giltigt och måste ändå ta sig säkert in i en databas. Det lyckas bara med prepared statements, som guiden [Förhindra SQL-injektion i PHP](https://phpsos.de/sv/ratgeber/sql-injection-php/) visar. Och en giltig kommentartext blir ofarlig först genom kontextanpassad kodning vid utmatning.

Rätt ordning är alltså: validera vid mottagandet, parametrisera vid bearbetningen, koda vid utmatningen. Dessutom hör storleksgränser dit i förväg: Förfrågningar som är alldeles för stora bör webbserver och PHP inte ens bearbeta fullständigt. Dit hör inställningar som `post_max_size`, som efter PHP2Shell ändå bör kontrolleras.

## Hur hjälper PHP SOS konkret?

- Vi registrerar alla ingångar i er applikation: formulär, gränssnitt, uppladdningar, importer och webhooks.
- Vi fastställer per fält vad som är tillåtet och ersätter generella saneringsfunktioner med tydliga kontroller.
- Vi kontrollerar om databasåtkomster och utmatningar är säkrade oberoende av valideringen.
- Vi dokumenterar reglerna så att ert team kan föra dem vidare vid nya funktioner.

En systematisk granskning beskriver tjänsten [säkerhetsaudit och penetrationstest](https://phpsos.de/sv/leistungen/sicherheitsaudit-penetrationstest/).


## Vanliga frågor

**Vad är skillnaden mellan att validera och att sanera?**  
Validering kontrollerar om ett värde motsvarar förväntningarna och avvisar det annars. Sanering ändrar värdet, till exempel genom att tecken tas bort. För säkerhetsbeslut är avvisande nästan alltid bättre, eftersom ett i tysthet ändrat värde kan ge nya fel.

**Går FILTER_SANITIZE_STRING fortfarande att använda?**  
Filtret är markerat som föråldrat sedan PHP 8.1. PHP-manualen rekommenderar i stället htmlspecialchars() vid utmatning. Befintlig kod bör ni ställa om, eftersom föråldrade funktioner kan försvinna i framtida versioner.

**Räcker FILTER_VALIDATE_URL för att göra länkar säkra?**  
Nej. Filtret kontrollerar bara adressens form. Enligt manualen behöver en giltig URL inte börja med http, därför måste ni själva kontrollera schemat mot en tillåtelselista som https. Internationaliserade domännamn avvisar filtret.

**Måste jag också validera data från min egen databas?**  
Vid utmatning räknas de som inte betrodda och kodas på lämpligt sätt. En ny validering är rimlig när datan ursprungligen kom utifrån och nu används i ett nytt sammanhang, till exempel som filnamn eller del av ett kommando.

**Hjälper validering mot PHP2Shell?**  
Nej. PHP2Shell gäller hanteringen av förfrågningar i PHP-tolken innan er applikationskod över huvud taget körs. Mot det hjälper bara PHP-uppdateringen med efterföljande omstart av alla PHP-processer.

## Källor

- [PHP-manualen: filterkonstanter](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/)
