8.5 Input validáció és adattisztítás
Áttekintő
Minden production-ready alkalmazásnak van egy alapvető szabálya, amit ha nem tartasz be, előbb-utóbb megégeted magad:
Soha ne bízz a felhasználói inputban.
Nem azért, mert a felhasználók rosszindulatúak (bár néha azok), hanem mert tévednek, elgépelnek, váratlan formátumot használnak – és a kódod ennek ellenére is helyesen kell, hogy működjön. Ez az alfejezet arról szól, hogyan szűröd és tisztítod meg az adatokat, mielőtt bármit csinálsz velük.
Miért számít ez az állásinterjún? A „hogyan validálod a felhasználói inputot?" típusú kérdés szinte minden web-fejlesztői interjún előjön. Ha az a válaszod, hogy „a frontend ellenőrzi", azonnal látszik, hogy nem értesz a production gondolkodásmódhoz.
Miért számít ez production-ban? Validáció nélkül: adatbázisban szemét adatok, elérhető hibák a felhasználónak, biztonsági rések. Validációval: megbízható, kiszámítható rendszer.
Részletes leírás
„Soha ne bízz a felhasználói inputban" – mit jelent ez pontosan?
Képzeld el, hogy van egy regisztrációs formód. A felhasználó megadja az email-t és az életkorát. Mi jöhet be az életkor mezőbe?
25– ez rendben van-5– negatív szám999– valószínűtlenül magashuszonöt– szöveg szám helyett- `` (üres string) – semmi
<script>alert('xss')</script>– rosszindulatú kód
A kódod mind a hat esettel találkozni fog éles környezetben. Validáció nélkül valamelyik összeomlást okoz, adatbázisszennyezést, vagy biztonsági rést.
Validáció vs. sanitizáció – nem ugyanaz
Sokan összekeverik ezt a két fogalmat. Fontos a különbség:
Validáció = eldöntöd, hogy az input érvényes-e, és ha nem, visszautasítod.
Például: az email mezőbe nem kerülhet üres string és érvényes email formátumot kell követnie. Ha nem felel meg, hibaüzenetet adsz vissza.
Sanitizáció (adattisztítás) = az inputot megváltoztatod, hogy biztonságos vagy megfelelő formátumú legyen.
Például: a beküldött szövegből kivágod a vezető/záró szóközöket (
" hello "→"hello"), vagy HTML-karaktereket enkódolsz, hogy ne lehessen scripteket injektálni.
A kettőt általában egymás után alkalmazod:
- Először sanitizálod (trimmelés, normalizálás)
- Aztán validálod (érvényes-e a tisztított adat?)
Kliens oldali vs. szerver oldali validáció
Ez az egyik legfontosabb megkülönböztetés, amit tudnod kell:
| Kliens oldali | Szerver oldali | |
|---|---|---|
| Hol fut? | Böngészőben (JavaScript) | Szerveren (backend) |
| Célja | UX javítása, azonnali visszajelzés | Valódi adatbiztonság |
| Megkerülhető? | Igen – bárki kikapcsolhatja | Nem – mindig lefut |
| Szükséges? | Ajánlott | Kötelező |
A kulcsgondolat: A kliens oldali validáció UX-eszköz, nem biztonsági eszköz.
Ha csak a böngészőben validálsz, bárki küldhet direkt HTTP kérést az API-odra a böngésző megkerülésével (pl. curl-lal vagy Postman-nel). A szerver oldali validáció mindig kötelező.
Jó gyakorlat:
Kliens oldali validáció → gyors visszajelzés a felhasználónak
Szerver oldali validáció → valódi adatbiztonság
Mindkettő egyszerre → production-ready megközelítés
Tipikus validálási esetek
1. Kötelező mező (required)
Az egyik legegyszerűbb és leggyakrabban elfelejtett ellenőrzés.
# Python
def validate_required(value, field_name):
if value is None or str(value).strip() == "":
raise ValueError(f"{field_name} megadása kötelező")
// JavaScript
function validateRequired(value, fieldName) {
if (value === null || value === undefined || String(value).trim() === "") {
throw new Error(`${fieldName} megadása kötelező`);
}
}
2. Email formátum
Ne írj saját regex-et email validáláshoz – használd a nyelved/frameworköd beépített eszközét.
# Python – email_validator könyvtár
from email_validator import validate_email, EmailNotValidError
try:
valid = validate_email("felhasznalo@pelda.hu")
except EmailNotValidError as e:
print(f"Hibás email: {e}")
// PHP – beépített filter_var
if (!filter_var($email, FILTER_VALIDATE_EMAIL)) {
throw new \InvalidArgumentException("Érvénytelen email cím");
}
// JavaScript – egyszerű regex CSAK UX célra (kliens oldal)
// Szerveren mindig könyvtárat használj!
const emailRegex = /^[^\s@]+@[^\s@]+\.[^\s@]+$/;
if (!emailRegex.test(email)) {
showError("Érvénytelen email formátum");
}
3. Szám és tartomány
# Python
def validate_age(age):
try:
age = int(age)
except (ValueError, TypeError):
raise ValueError("Az életkor szám kell legyen")
if age < 0 or age > 120:
raise ValueError("Az életkor 0 és 120 közé kell essen")
return age
4. Hossz ellenőrzés
// JavaScript
function validatePassword(password) {
if (password.length < 8) {
throw new Error("A jelszó legalább 8 karakter hosszú kell legyen");
}
if (password.length > 128) {
throw new Error("A jelszó maximum 128 karakter lehet");
}
}
5. Típus ellenőrzés
Különösen fontos JSON API-knál, ahol a kliens bármilyen típust küldhet.
# Python – típus ellenőrzés API inputnál
def validate_product_data(data):
if not isinstance(data.get("price"), (int, float)):
raise ValueError("Az ár szám kell legyen")
if not isinstance(data.get("name"), str):
raise ValueError("A név szöveg kell legyen")
if not isinstance(data.get("in_stock"), bool):
raise ValueError("Az 'in_stock' mező igaz/hamis értéket várunk")
Sanitizáció a gyakorlatban
Trimmelés (szóközök eltávolítása)
Az egyik leggyakoribb – és leginkább elfelejtett – lépés.
# Mindig trim-eld a szöveges inputot!
name = request.form.get("name", "").strip()
email = request.form.get("email", "").strip().lower()
const name = req.body.name?.trim() ?? "";
const email = req.body.email?.trim().toLowerCase() ?? "";
Ha nem trim-elted, " admin " és "admin" különböző felhasználóként kerülhet az adatbázisba.
HTML escape (XSS megelőzés)
Ha a felhasználó által bevitt szöveget HTML-be rendereled vissza, enkódold:
# Python – html modul
import html
user_comment = html.escape(raw_comment)
# "<script>alert('xss')</script>" → "<script>alert('xss')</script>"
// PHP – htmlspecialchars
$safe_output = htmlspecialchars($user_input, ENT_QUOTES, 'UTF-8');
Fontos: Modern frameworkök (Laravel Blade, Django templates, React JSX) alapból enkódolnak HTML-t, ha helyesen használod őket. De tudnod kell, hogy ez mikor és miért történik.
Visszajelzés validációs hibáról
A validáció nem csak arról szól, hogy visszautasítod a hibás inputot – arról is, hogy hasznos hibaüzenetet adsz.
Rossz visszajelzés:
Hiba: 400 Bad Request
Jó visszajelzés:
{
"errors": {
"email": "Érvénytelen email cím formátum",
"password": "A jelszó legalább 8 karakter hosszú kell legyen",
"age": "Az életkor 0 és 120 közé kell essen"
}
}
Elvek a jó hibaüzenethez:
- Specifikus: melyik mező hibás?
- Cselekvésre ösztönző: mit kell javítani?
- Nem technikai: nem stack trace, nem adatbázis-hiba
- Összes hiba egyszerre: ne csak az első hibát add vissza
Validáció elhelyezése az alkalmazásban
HTTP kérés → [Router] → [Validáció] → [Üzleti logika] → [Adatbázis]
↓
Ha érvénytelen:
400 Bad Request + hibák listája
A validáció a legelső réteg, mielőtt az üzleti logika egyáltalán lefutna.
Életszerű példák
Példa 1: Regisztrációs form handler – validáció nélkül vs. validációval
Validáció nélkül (tutorial-kód):
# ROSSZ – soha ne csinálj ilyet production-ban
@app.route("/register", methods=["POST"])
def register():
username = request.form["username"]
email = request.form["email"]
password = request.form["password"]
age = request.form["age"]
# Közvetlenül az adatbázisba – minden ellenőrzés nélkül
db.execute(
"INSERT INTO users (username, email, password, age) VALUES (?, ?, ?, ?)",
(username, email, hash_password(password), age)
)
return "Sikeres regisztráció!"
Mi mehet rosszul?
ageértéke"huszonöt"→ adatbázis hiba, ami kiszivárog a felhasználónakemailértéke üres → kerülhet üres email az adatbázisbausernamehossza ezer karakter → adatbázis column overflowpasswordüres → üres hash kerül be
Validációval (production-közelibb megközelítés):
@app.route("/register", methods=["POST"])
def register():
errors = {}
# Sanitizáció először
username = request.form.get("username", "").strip()
email = request.form.get("email", "").strip().lower()
password = request.form.get("password", "")
age_raw = request.form.get("age", "").strip()
# Validáció
if not username:
errors["username"] = "A felhasználónév megadása kötelező"
elif len(username) < 3 or len(username) > 50:
errors["username"] = "A felhasználónév 3-50 karakter hosszú lehet"
if not email:
errors["email"] = "Az email cím megadása kötelező"
elif not is_valid_email(email):
errors["email"] = "Érvénytelen email formátum"
if not password:
errors["password"] = "A jelszó megadása kötelező"
elif len(password) < 8:
errors["password"] = "A jelszó legalább 8 karakter hosszú kell legyen"
try:
age = int(age_raw)
if age < 0 or age > 120:
errors["age"] = "Az életkor 0-120 közötti szám kell legyen"
except ValueError:
errors["age"] = "Az életkor érvényes szám kell legyen"
# Ha van hiba, visszaadjuk az összeset
if errors:
return jsonify({"errors": errors}), 400
# Csak ekkor fut az üzleti logika
db.execute(
"INSERT INTO users (username, email, password_hash, age) VALUES (?, ?, ?, ?)",
(username, email, hash_password(password), age)
)
return jsonify({"message": "Sikeres regisztráció!"}), 201
Példa 2: A "csak JavaScript-ben validálok" csapda
Egy junior fejlesztő csak frontend validációt írt:
// Frontend validáció (böngészőben fut)
document.getElementById("register-form").addEventListener("submit", (e) => {
const age = document.getElementById("age").value;
if (isNaN(age) || age < 0 || age > 120) {
e.preventDefault();
showError("Érvénytelen életkor");
}
});
Egy tesztelő (vagy rosszindulatú felhasználó) terminálból:
curl -X POST https://app.pelda.hu/register \
-d "username=test&email=test@test.hu&password=12345678&age=INJECTED_PAYLOAD"
A böngésző JavaScript egyáltalán nem futott le. A szerver megkapta az INJECTED_PAYLOAD értéket validáció nélkül.
Példa 3: Laravel és PHP keretrendszer – validáció beépítve
Modern keretrendszerek beépített validációt nyújtanak:
// Laravel Controller
public function store(Request $request)
{
// A framework validálja, és automatikusan 422-t ad vissza ha hibás
$validated = $request->validate([
'username' => 'required|string|min:3|max:50',
'email' => 'required|email|unique:users,email',
'password' => 'required|min:8|max:128',
'age' => 'required|integer|min:0|max:120',
]);
// Ha idáig eljutunk, az adatok érvényesek
User::create([
'username' => $validated['username'],
'email' => $validated['email'],
'password_hash' => bcrypt($validated['password']),
'age' => $validated['age'],
]);
return response()->json(['message' => 'Sikeres regisztráció!'], 201);
}
A keretrendszer elvégzi a validációt, és automatikusan visszaküldi a hibaüzeneteket, ha az input nem megfelelő. A te feladatod csak a szabályokat megadni.
Tesztfeladatok
1. feladat – Fogalmak ellenőrzése
Döntsd el, hogy az alábbi műveletek validáció vagy sanitizáció kategóriába esnek-e:
a) A beküldött email cím kisbetűssé alakítása
b) Ellenőrzés, hogy az email cím tartalmaz @ karaktert
c) A szöveg elejéről és végéről szóközök eltávolítása
d) Ellenőrzés, hogy a felhasználónév nem hosszabb 50 karakternél
e) HTML-karakterek enkódolása a felhasználó kommentjéből
2. feladat – Kliens vs. szerver oldal
Az alábbi szituációkban jelöld meg, hogy kliens oldali, szerver oldali, vagy mindkét oldali validáció szükséges-e, és indokold meg:
a) Regisztrációs formon az email mező formátumának ellenőrzése
b) Ellenőrzés, hogy az email cím nincs-e már regisztrálva az adatbázisban
c) Jelszó minimális hosszának ellenőrzése
d) Feltöltött kép méretének (fájlméret) ellenőrzése
e) Fizetési összeg pozitivitásának ellenőrzése egy rendelésnél
3. feladat – Hibakeresés
Az alábbi Python kódrészletben legalább 3 validációs problémát találsz. Azonosítsd őket és javasold a javítást:
@app.route("/create-post", methods=["POST"])
def create_post():
title = request.form["title"]
content = request.form["content"]
author_id = request.form["author_id"]
db.execute(
"INSERT INTO posts (title, content, author_id) VALUES (?, ?, ?)",
(title, content, author_id)
)
return "Post létrehozva!"
4. feladat – Hibaüzenet minőség
Értékeld az alábbi API hibaválaszokat 1-5-ös skálán (5 = legjobb) és indokold:
A válasz:
HTTP 500 Internal Server Error
Column 'email' cannot be null
B válasz:
HTTP 400 Bad Request
{"error": "Hibás adatok"}
C válasz:
HTTP 422 Unprocessable Entity
{
"errors": {
"email": "Az email cím megadása kötelező",
"password": "A jelszó legalább 8 karakter hosszú kell legyen"
}
}
5. feladat – Igaz/hamis állítások
Döntsd el, hogy az alábbi állítások igazak vagy hamisak, és magyarázd meg:
a) Ha a frontend validálja az inputot, a backendnek már nem kell.
b) A sanitizáció mindig megelőzi a validációt.
c) Az email validáláshoz mindig saját regex-et érdemes írni.
d) Egy API-nál szerver oldali validáció kötelező, még akkor is, ha van kliens oldali is.
e) A trim (szóköz eltávolítás) sanitizáció, nem validáció.
6. feladat – Kódkiegészítés
Az alábbi JavaScript függvény részleges validációt végez. Egészítsd ki a hiányzó ellenőrzésekkel (csak a logikát kell leírni, nem kell futtatható kódot írni):
function validateProductData(data) {
const errors = {};
// TODO: name mező: kötelező, 2-100 karakter között
// TODO: price mező: kötelező, pozitív szám
// TODO: quantity mező: opcionális, de ha meg van adva, egész szám, minimum 0
return errors;
}
Írd le, hogy melyik ellenőrzést hogyan implementálnád (pszeudokódban vagy bármilyen nyelven).
7. feladat – Szituációs döntés
Fejlesztőként az alábbi szituációkkal találkozol. Mit teszel?
a) Egy kollégád azt mondja: „Felesleges szerver oldali validáció, a frontend úgyis ellenőrzi." Hogyan érvelsz mellette?
b) Production adatbázisban sok felhasználónak üres az email mezője, mert régebben nem volt kötelező. Hogyan előzöd meg, hogy ez a jövőben is előforduljon?
c) Egy felhasználó bejelentette, hogy az ő nevével ("O'Brien") nem tud regisztrálni – hibát kap. Mi lehet az ok, és hogyan javítod?
8. feladat – Kódelemzés
Az alábbi PHP kód mit csinál, és mi a probléma vele?
<?php
$username = $_POST['username'];
$username = trim($username);
if (strlen($username) > 0) {
echo "Szia, " . $username . "!";
} else {
echo "Kérjük adja meg a nevét!";
}
?>
Tipp: gondolj arra, mi történik, ha valaki ezt adja meg: <script>alert('XSS')</script>
9. feladat – Architektúra kérdés
Egy webshopban a felhasználó megad egy mennyiséget (1-99 között), amit szeretne rendelni. Tervezd meg a validáció teljes folyamatát:
- Hol és mit validálsz a frontenden?
- Hol és mit validálsz a backenden?
- Mi legyen a hibaüzenet, ha érvénytelen az érték?
- Mi a sorrend: sanitizáció vagy validáció előbb?
10. feladat – Összefoglalás
Egy junior kolléga azt mondja: „Megírtam a validációt, de csak annyit csináltam, hogy ha üres a mező, hibát adok vissza."
Milyen validációs eseteket felejtett el valószínűleg? Sorolj fel legalább 5-öt, amelyeket még érdemes lenne ellenőrizni egy tipikus felhasználói regisztrációs formon.
Fejezet: 8. Production-ready projekt építés | Alfejezet: 8.5 Input validáció és adattisztítás