14-bo‘lim
Formalar va validatsiya
HTML forma ma'lumotini o'qish, JSON bilan farqi, maydonlar bo'yicha tekshirish, 400 va 422 kodlari hamda ma'lumotni tozalash.
Ushbu bo‘lim mundarijasi
Foydalanuvchidan kelgan har qanday ma'lumot - ishonchsiz. Uni tekshirmasdan ishlatish eng keng tarqalgan xavfsizlik xatosi.
Ikki xil forma ma'lumoti #
import express from "express";
const app = express();
app.use(express.json());
app.use(express.urlencoded({ extended: true }));
app.post("/qabul", (sorov, javob) => {
javob.json({ turi: sorov.get("content-type"), tana: sorov.body });
});
const server = app.listen(0);
const port = server.address().port;
const asos = `http://localhost:${port}/qabul`;
const json = await fetch(asos, {
method: "POST",
headers: { "Content-Type": "application/json" },
body: JSON.stringify({ ism: "Malika", yosh: 20 }),
});
console.log(await json.json());
const forma = await fetch(asos, {
method: "POST",
headers: { "Content-Type": "application/x-www-form-urlencoded" },
body: new URLSearchParams({ ism: "Aziza", yosh: "19" }),
});
console.log(await forma.json());
server.close();
{ turi: 'application/json', tana: { ism: 'Malika', yosh: 20 } }
{
turi: 'application/x-www-form-urlencoded',
tana: { ism: 'Aziza', yosh: '19' }
}
Ikkita muhim farqni ko'ring:
| JSON | HTML forma | |
|---|---|---|
| Qatlam | express.json() | express.urlencoded() |
| Son turi | Son bo'lib keladi | Satr bo'lib keladi |
yosh: '19' - qo'shtirnoq ichida. HTML forma faqat matn
yuboradi; sonlar, sanalar, mantiqiy qiymatlar - hammasi satr.
Bu 6-bo'limdagi process.env va 12-bo'limdagi sorov.params bilan
bir xil tuzoq. Uchalasida ham qoida bitta: aylantiring va
tekshiring.
express.urlencoded({ extended: true }) - ichma-ich obyektlarni
ham tushunadi (foydalanuvchi[ism]). false bo'lsa, faqat oddiy
kalit-qiymat.
Oddiy tekshiruv #
function talabaniTekshir(malumot) {
const xatolar = {};
const ism = String(malumot.ism ?? "").trim();
if (ism.length < 2) {
xatolar.ism = "ism kamida 2 belgidan iborat bo'lsin";
} else if (ism.length > 50) {
xatolar.ism = "ism 50 belgidan oshmasin";
}
const ball = Number(malumot.ball);
if (!Number.isInteger(ball)) {
xatolar.ball = "ball butun son bo'lsin";
} else if (ball < 0 || ball > 100) {
xatolar.ball = "ball 0 va 100 orasida bo'lsin";
}
return { toza: { ism, ball }, xatolar };
}
console.log(talabaniTekshir({ ism: " Malika ", ball: "88" }));
console.log(talabaniTekshir({ ism: "M", ball: 150 }));
console.log(talabaniTekshir({}));
{ toza: { ism: 'Malika', ball: 88 }, xatolar: {} }
{
toza: { ism: 'M', ball: 150 },
xatolar: {
ism: "ism kamida 2 belgidan iborat bo'lsin",
ball: "ball 0 va 100 orasida bo'lsin"
}
}
{
toza: { ism: '', ball: NaN },
xatolar: {
ism: "ism kamida 2 belgidan iborat bo'lsin",
ball: "ball butun son bo'lsin"
}
}
Uch tamoyil:
- Tozalash -
trim(), keraksiz bo'shliqni olib tashlash. - Aylantirish -
Number(),String(). - Hamma xatoni yig'ish - birinchisida to'xtamaslik.
Serverga ulash #
import express from "express";
const app = express();
app.use(express.json());
function tekshir(malumot) {
const xatolar = {};
const ism = String(malumot.ism ?? "").trim();
if (ism.length < 2) xatolar.ism = "juda qisqa";
const ball = Number(malumot.ball);
if (!Number.isInteger(ball) || ball < 0 || ball > 100) {
xatolar.ball = "0 va 100 orasida butun son bo'lsin";
}
return { toza: { ism, ball }, xatolar };
}
app.post("/talabalar", (sorov, javob) => {
const { toza, xatolar } = tekshir(sorov.body ?? {});
if (Object.keys(xatolar).length > 0) {
javob.status(422).json({ xato: "tekshiruvdan o'tmadi", xatolar });
return;
}
javob.status(201).json({ yaratildi: toza });
});
const server = app.listen(0);
const port = server.address().port;
const asos = `http://localhost:${port}/talabalar`;
const yubor = async (tana) => {
const j = await fetch(asos, {
method: "POST",
headers: { "Content-Type": "application/json" },
body: JSON.stringify(tana),
});
return [j.status, await j.json()];
};
console.log(await yubor({ ism: "Nodira", ball: 91 }));
console.log(await yubor({ ism: "X", ball: 500 }));
server.close();
[ 201, { yaratildi: { ism: 'Nodira', ball: 91 } } ]
[
422,
{
xato: "tekshiruvdan o'tmadi",
xatolar: { ism: 'juda qisqa', ball: "0 va 100 orasida butun son bo'lsin" }
}
]
Ikkalasi ham "mijoz xatosi", lekin ma'nosi boshqa:
- 400 Bad Request - so'rovning shakli buzuq. Masalan JSON o'qib bo'lmadi yoki kerakli sarlavha yo'q.
- 422 Unprocessable Content - shakl to'g'ri, lekin mazmuni qoidalarga mos emas. JSON o'qildi, ammo ball 500 edi.
Amalda ko'p loyihalar faqat 400 ishlatadi va bu ham normal. Muhimi - izchil bo'lish: bitta API ichida bir xil holat uchun bir xil kod qaytarsin.
Eng muhimi - xato qaysi maydonda ekanini ayting. Shunda interfeys uni to'g'ri maydon tagida ko'rsata oladi.
Buzuq JSON #
import express from "express";
const app = express();
app.use(express.json());
app.post("/", (s, j) => j.json({ holat: "qabul qilindi" }));
app.use((xato, sorov, javob, keyingi) => {
if (xato instanceof SyntaxError && "body" in xato) {
javob.status(400).json({ xato: "JSON o'qib bo'lmadi" });
return;
}
javob.status(500).json({ xato: "ichki xato" });
});
const server = app.listen(0);
const port = server.address().port;
const buzuq = await fetch(`http://localhost:${port}/`, {
method: "POST",
headers: { "Content-Type": "application/json" },
body: "{ bu json emas",
});
console.log(buzuq.status, await buzuq.json());
server.close();
400 { xato: "JSON o'qib bo'lmadi" }
express.json() buzuq JSON uchun SyntaxError tashlaydi. Uni
ushlamasangiz, mijoz 500 oladi - go'yo server aybdordek.
Aslida aybdor mijoz, shuning uchun 400 to'g'riroq.
Ruxsat etilgan maydonlar #
function faqatRuxsatEtilgan(malumot, ruxsat) {
const natija = {};
for (const kalit of ruxsat) {
if (kalit in malumot) natija[kalit] = malumot[kalit];
}
return natija;
}
const kelgan = {
ism: "Malika",
ball: 88,
rol: "admin",
id: 999,
};
console.log(faqatRuxsatEtilgan(kelgan, ["ism", "ball"]));
{ ism: 'Malika', ball: 88 }
Bu juda xavfli naqsh:
await baza.yarat(sorov.body); // hammasi o'tadi
Yuqoridagi misolda mijoz rol: "admin" va id: 999 yuborgan edi.
Agar butun obyektni saqlasangiz, foydalanuvchi o'zini admin qilib
qo'yishi mumkin.
Bu ommaviy tayinlash (mass assignment) zaifligi deb ataladi va u haqiqiy tizimlarda tez-tez uchraydi.
Himoya: ruxsat etilganlar ro'yxati (allow-list). Qaysi maydon kerak bo'lsa, faqat o'shani oling. "Taqiqlanganlar ro'yxati" esa yomon - yangi maydon qo'shilganda uni unutish oson.
Tozalash #
function tozala(matn) {
return String(matn ?? "")
.trim()
.replace(/\s+/g, " ")
.slice(0, 100);
}
console.log(`"${tozala(" Malika Karimova ")}"`);
console.log(`"${tozala(null)}"`);
console.log(tozala("a".repeat(200)).length);
function emailTogrimi(email) {
const t = String(email ?? "").trim().toLowerCase();
return /^[^\s@]+@[^\s@]+\.[^\s@]+$/.test(t) ? t : null;
}
console.log(emailTogrimi(" [email protected] "));
console.log(emailTogrimi("notogri"));
"Malika Karimova"
""
100
[email protected]
null
Yuqoridagi naqsh juda oddiy va u ataylab shunday.
To'liq to'g'ri email naqshi yuzlab belgidan iborat bo'ladi va baribir hamma holatni qamrab olmaydi. Undan tashqari, murakkab naqshlar ReDoS hujumiga ochiq bo'lishi mumkin: maxsus tanlangan satr regulyar ifodani soatlab ishlashga majbur qiladi.
Amaliy yondashuv: oddiy tekshiruv qiling (@ va nuqta bor), keyin
tasdiqlash xati yuboring. Emailning haqiqiyligini faqat shu
usul isbotlaydi.
express.urlencodedbilan HTML forma ma'lumotini o'qing.- Formadan kelgan son satr ekanini ko'rsating.
- Ism va ballni tekshiradigan funksiya yozing.
- Hamma xatoni birdaniga qaytaring.
- Xatolarni maydon nomi bilan yuboring.
- 422 holat kodini qaytaring.
- Buzuq JSON yuborib, 400 ni oling.
- Ruxsat etilgan maydonlar ro'yxatini yozing.
rol: "admin"yuborib, u o'tmasligini isbotlang.- Matnni
trimva uzunlik bilan tozalang.
Xulosa #
- JSON uchun
express.json(), HTML forma uchunexpress.urlencoded(). - Formadan kelgan hamma narsa satr - aylantiring va tekshiring.
- Tekshiruv uch qadam: tozalash, aylantirish, hamma xatoni yig'ish.
- Xatoni maydon nomi bilan qaytaring.
400- so'rov shakli buzuq,422- mazmuni qoidaga mos emas; eng muhimi izchillik.- Buzuq JSON uchun
SyntaxErrorni ushlab, 400 qaytaring. - Kelgan obyektni to'g'ridan-to'g'ri saqlamang - ruxsat etilgan maydonlar ro'yxatini ishlating.
- Email uchun murakkab naqsh emas, tasdiqlash xati.
Keyingi bo'limda REST API quramiz.
O‘qish tarixini saqlamoqchimisiz?
Tizimga kirsangiz, tugatgan bo‘limlaringiz saqlanadi va qoldirgan joyingizdan davom etasiz.
Xatolik topdingizmi?
Imlo xatosi, ishlamaydigan kod yoki noto‘g‘ri ma‘lumotni ko‘rsangiz - bizga xabar bering. Har bir xabar administrator tomonidan ko‘rib chiqiladi.