IlmHamroh
JavaScript Full-stack/11-qism. Asinxron JavaScript va tarmoq27/32-dars18 daqiqa
Mundarija (34)

Cookie'lar JavaScript'dan: document.cookie, atributlar va Cookie Store API

Qisqacha: Cookie — brauzer shu saytga har so'rov bilan o'zi qo'shib yuboradigan kichik yozuv. JavaScript'dan document.cookie = "til=uz; Max-Age=31536000" bilan bitta cookie yoziladi, document.cookie ni o'qisangiz esa hammasi bitta satrda keladi: "til=uz; tema=qorongi". HttpOnly belgili cookie'ni JavaScript umuman ko'rmaydi — shuning uchun sessiya va kirish tokenlari aynan shunday cookie'da saqlanadi.

Bu darsda

  • document.cookie bilan cookie yozasiz, o'qiysiz, yangilaysiz va o'chirasiz.
  • Max-Age/Expires, Path, Domain, Secure, SameSite atributlarini qachon qo'yishni bilasiz.
  • HttpOnly cookie'ni nega JavaScript ko'rmasligini va bu qanday himoya ekanini tushuntira olasiz.
  • Zamonaviy Cookie Store API bilan (cookieStore.get/set/delete, change hodisasi) asinxron ishlaysiz.
  • Kirish tokenini qayerda saqlash kerakligi haqidagi bahsda dalil bilan gapira olasiz.

Oldin bilishingiz kerak: HTTP sarlavhalari, MIME turlari, cookie va kesh, Brauzer xotirasi va xavfsizlik modeli, localStorage va sessionStorage, async / await.

1. Nega bu kerak?

O'tgan darsdagi localStorage ma'lumoti brauzerda qoladi — server undan bexabar. Lekin ba'zi narsani server bilishi shart:

  • Dilshod aka «Bahor» saytiga kirdi. Keyingi har sahifada server "bu o'sha Dilshod aka" deb bilishi kerak — aks holda har sahifada parol so'raladi.
  • Mehmon tilni "Русский" ga o'zgartirdi. Server sahifani yuborishdan oldin qaysi tilda tayyorlashni bilishi kerak.

HTTP sarlavhalari darsida ko'rdik: server Set-Cookie sarlavhasi bilan cookie beradi, brauzer uni saqlaydi va keyingi so'rovlarda Cookie sarlavhasida qaytaradi. Bu ishni server boshqaradi. Bugun o'sha cookie'larga JavaScript tomonidan qaraymiz: ularni qanday o'qish va yozish mumkin, qaysilarini — yo'q, va nega.

Brauzer xotirasi darsidagi o'xshatish: cookie — cho'ntakdagi kichik qog'oz. Joyi kam, lekin shu saytga har borganingizda o'zingiz bilan olib borasiz.

Diagrammada cookie'ning butun yo'li. Qarang: brauzer cookie'ni o'zi saqlaydi va o'zi yuboradi, JavaScript esa faqat bir qismini ko'radi.

sequenceDiagram
    participant S as Server
    participant B as Brauzer
    participant J as Sahifadagi JS
    S->>B: Set-Cookie: til=uz
    S->>B: Set-Cookie: sessiya (HttpOnly)
    B->>S: keyingi so'rov: Cookie sarlavhasida ikkalasi
    J->>B: document.cookie ni o'qiydi
    B-->>J: "til=uz" (HttpOnly yo'q)

2.1 Yozish — bittadan

document.cookie — joriy sahifa uchun cookie'larga JavaScript'dan kirish yo'li. U oddiy xususiyatga o'xshaydi, lekin aslida getter va setter juftligi. Yozish va o'qish butunlay boshqa-boshqa ish qiladi:

html
<script>
  document.cookie = "til=uz";
  document.cookie = "tema=qorongi";
  console.log(document.cookie);

  document.cookie = "til=ru";
  console.log(document.cookie);
</script>

Konsolda:

text
til=uz; tema=qorongi
tema=qorongi; til=ru

Uch narsaga qarang:

  1. Yozish qo'shadi, ustidan yozmaydi. Ikkinchi qator til ni o'chirmadi — tema yoniga qo'shildi. Bitta tayinlash = bitta cookie.
  2. O'qish hammasini beradi — bitta satrda, "; " (nuqta-vergul va bo'sh joy) bilan ajratilgan.
  3. Nom bir xil bo'lsa — yangilanadi. til=ru eski til=uz o'rnini oldi. Chrome yangilangan cookie'ni ro'yxat oxiriga qo'ydi.

Natija oynasida cookie ham sayt bergan o'rinbosar orqali ishlaydi va «Qayta ishga tushirish» da saqlanadi — localStorage dagi kabi. Haqiqiy saytda bu brauzerning o'z cookie qutisi.

2.2 O'qish — o'zingiz ajratasiz

Bitta cookie'ning qiymati kerak bo'lsa, satrni o'zingiz bo'laklaysiz. Brauzer tayyor get bermaydi (buni hal qiladigan yangi API — "Cookie Store API" bo'limida):

html
<script>
  document.cookie = "til=uz";
  document.cookie = "savat=" + encodeURIComponent("osh,manti");

  function cookieniOl(nom) {
    for (const juft of document.cookie.split("; ")) {
      const belgi = juft.indexOf("=");
      if (juft.slice(0, belgi) === nom) {
        return decodeURIComponent(juft.slice(belgi + 1));
      }
    }
    return null;
  }

  console.log(document.cookie);
  console.log(cookieniOl("til"));
  console.log(cookieniOl("savat"));
  console.log(cookieniOl("yoq"));
</script>

Konsolda:

text
til=uz; savat=osh%2Cmanti
uz
osh,manti
null

Nega split("=") emas, indexOf("=")? Qiymatning ichida ham = bo'lishi mumkin (masalan, base64 matn abc== bilan tugaydi). Birinchi = gacha — nom, qolgani — qiymat.

encodeURIComponent va decodeURIComponent nima qilyapti — bir oz pastda, "Qiymatni kodlash" bo'limida.

Tekshirib ko'ring: document.cookie = "a=1; b=2"; yozildi. Nechta cookie paydo bo'ladi?

Javob

Bitta: a=1. Birinchi ; dan keyingi hamma narsa atribut deb o'qiladi — b=2 esa noma'lum atribut sifatida tashlab yuboriladi. Bitta tayinlash — har doim bitta cookie. Ikkita kerak bo'lsa — ikki marta yozing.

3. Atributlar: qancha yashaydi va qayerga boradi

3.1 Muddat: Max-Age va Expires

Yozish satrida ; dan keyin atributlar keladi. Ular brauzerga cookie haqida qo'shimcha ko'rsatma beradi. Eng muhimi — muddat:

  • Muddat yozilmasa — sessiya cookie'si: brauzer yopilganda o'chadi.
  • Max-Age=60 — 60 soniya yashaydi.
  • Expires=Fri, 01 Jan 2027 00:00:00 GMT — aniq sanagacha. Bu eski usul; Max-Age sodda va soat mintaqasiga bog'liq emas.

Muddat o'tgan cookie'ni brauzer o'zi o'chiradi. Ko'ring — bir soniyalik aksiya cookie'si:

html
<script>
  document.cookie = "aksiya=1; Max-Age=1";
  document.cookie = "til=uz; Max-Age=31536000";
  console.log("Hozir:", document.cookie);

  setTimeout(() => {
    console.log("1,5 s dan keyin:", document.cookie);
  }, 1500);
</script>

Konsolda:

text
Hozir: aksiya=1; til=uz
1,5 s dan keyin: til=uz

31536000 — bir yildagi soniyalar soni (365 × 24 × 60 × 60). Undan ham uzoq muddat bersangiz, Chrome uni 400 kun bilan cheklaydi — Chrome 154 da 500 kun yozib tekshirdik, saqlangani 400 kun chiqdi. Bu cheklov endi standartda ham bor.

3.2 O'chirish — muddatni o'tkazish

Cookie'ni o'chiradigan alohida metod yo'q. O'chirish uchun xuddi shu nom bilan muddati o'tgan cookie yoziladi:

html
<script>
  document.cookie = "til=uz";
  document.cookie = "tema=qorongi";
  document.cookie = "til=; Max-Age=0";
  console.log(document.cookie);
</script>

Konsolda:

text
tema=qorongi

Max-Age=0 (yoki Expires ga o'tgan sana) — "darhol eskirdi". Qiymat bo'sh bo'lishi shart emas, lekin odatda bo'sh yoziladi.

Diqqat: Cookie Path yoki Domain bilan yozilgan bo'lsa, uni o'chirishda ham aynan o'sha Path va Domain yozilishi kerak. Aks holda brauzer buni boshqa cookie deb biladi va asl cookie joyida qoladi. Bu — "cookie o'chmayapti!" shikoyatining eng ko'p sababi.

3.3 Path va Domain: kim ko'radi

  • Path=/menyu — cookie faqat /menyu va uning ichidagi manzillarga yuboriladi va faqat o'sha sahifalardagi document.cookie da ko'rinadi. Yozilmasa — joriy sahifaning papkasi. Shuning uchun deyarli har doim Path=/ yoziladi: "butun sayt uchun".
  • Domain=example.com — cookie example.com ga ham, uning subdomenlariga (menyu.example.com) ham boradi. Yozilmasa — faqat aynan joriy host. Begona domen yozib bo'lmaydi: brauzer bunday cookie'ni rad etadi.

Live Server bilan tekshirdik (Chrome 154): /menyu/ sahifasida document.cookie = "tanlov=osh; Path=/menyu" yozildi. Shu sahifada u ko'rinadi. Bosh sahifa / ga o'tganda esa document.cookie da tanlov yo'q.

Natija oynasi bitta "sahifa" — u Path va Domain ni farqlamaydi. Bu ikkisini kompyuteringizda Live Server bilan sinang.

3.4 Secure va SameSite

  • Secure — cookie faqat HTTPS orqali yuboriladi. Ochiq HTTP'da (masalan, kafe Wi-Fi'ida) uni yo'lda o'qib bo'lmaydi. Istisno: localhost va 127.0.0.1 — ishlab chiqish uchun ular xavfsiz deb hisoblanadi.
  • SameSite — begona saytdan boshlangan so'rovga cookie qo'shiladimi:
    • Strict — faqat shu saytning o'zidan boshlangan so'rovlarga.
    • Lax — yana boshqa saytdagi havoladan o'tganda ham (lekin begona saytdagi formaning POST iga — yo'q). Yozilmasa, Chrome shuni qo'llaydi.
    • None — har qanday so'rovga. Faqat Secure bilan birga ishlaydi.

Misol: Dilshod aka Telegram'dagi havolani bosib «Bahor» saytiga o'tdi. Sessiya cookie'si Lax bo'lsa — u saytda "kirgan" holda ochiladi. Strict bo'lsa — birinchi sahifada "kirmagan" bo'lib ko'rinadi, chunki so'rov begona joydan (Telegram'dan) boshlandi.

Oxirgi qoidani sinaymiz:

html
<script>
  document.cookie = "a=1; SameSite=None";
  document.cookie = "b=1; SameSite=None; Secure";
  document.cookie = "sessiya=abc123; HttpOnly";
  console.log(document.cookie);
</script>

Konsolda:

text
b=1

a — Secure siz SameSite=None: brauzer jim rad etdi, xato ham chiqmadi. sessiya ham yo'q — HttpOnly haqida keyingi bo'limda. Natija Chrome 154 da Live Server bilan ham bir xil chiqdi.

DevTools → Application → Cookies da har cookie'ning hamma atributi jadvalda ko'rinadi. "Nega cookie yo'q?" savolida eng tez yo'l — Network panelida so'rovni tanlab, Cookies yorlig'iga qarash: rad etilgan cookie u yerda sariq belgi bilan va sababi bilan turadi.

Siz https://example.com ni ochdingiz. U yerdagi cookie — birinchi tomon (first-party) cookie'si: manzil satridagi sayt bilan bir xil saytniki. Sahifa ichida esa boshqa saytdan reklama yoki "Like" tugmasi turibdi. Uning cookie'si — uchinchi tomon (third-party) cookie'si: manzil satrida yo'q saytniki.

Uchinchi tomon cookie'lari tarixan foydalanuvchini saytdan saytga kuzatish uchun ishlatilgan: bitta reklama tarmog'i yuzlab saytda "bu o'sha odam" deb bilgan. Shuning uchun Safari va Firefox ularni standart bo'yicha bloklaydi, Chrome esa foydalanuvchiga tanlov beradi. Begona sayt ichida ishlashi kerak bo'lgan vidjet (masalan, chat oynasi) uchun Partitioned atributi bor: bunday cookie har "ota" sayt uchun alohida qutida saqlanadi va saytdan saytga o'tmaydi. U ham faqat Secure bilan ishlaydi.

Bizning vazifalar va «Bahor» — birinchi tomon. Sahifa begona sayt ichidagi iframe'da ochilganda "cookie ishlamayapti" bo'lsa — sababi ko'pincha shu.

fetch asoslari darsida so'rov yuborgansiz. Cookie'lar so'rovga qachon qo'shiladi? fetch ning credentials opsiyasi hal qiladi (fetch opsiyalari):

  • "same-origin" (standart) — faqat o'z origin'ingizga so'rovda.
  • "include" — boshqa origin'ga ham. Server buni CORS bilan alohida ruxsat bergan bo'lishi shart (CORS mijoz tomondan).
  • "omit" — hech qachon.

Ya'ni JavaScript cookie qiymatini ko'rmasa ham (HttpOnly), so'rovga qo'shilishini boshqara oladi. Server javobidagi Set-Cookie ni esa fetch ham ko'rsatmaydi: response.headers.get("set-cookie") — null. Brauzer uni o'zi oladi va cookie qutisiga yozadi.

Tekshirib ko'ring: Sardor document.cookie = "til=uz; Path=/menyu" yozdi, keyin bosh sahifada document.cookie = "til=; Max-Age=0" bilan o'chirmoqchi bo'ldi. /menyu sahifasida til qoladimi?

Javob

Qoladi. O'chirish satrida Path yo'q — brauzer uni bosh sahifa papkasidagi boshqa til deb tushundi. To'g'risi: document.cookie = "til=; Max-Age=0; Path=/menyu".

4.1 Faqat server qo'ya oladi

HttpOnly atributi — "bu cookie faqat HTTP so'rovlar uchun". Brauzer uni so'rovlarga qo'shadi, lekin document.cookie da ko'rsatmaydi. Yuqoridagi tajribada sessiya=abc123; HttpOnly umuman saqlanmadi — JavaScript HttpOnly cookie yarata olmaydi. Uni faqat server javobidagi sarlavha beradi:

text
HTTP/1.1 200 OK
Set-Cookie: sessiya=abc123; HttpOnly; Secure; SameSite=Lax; Path=/; Max-Age=86400
Set-Cookie: til=uz; Path=/; Max-Age=31536000

Shu javobdan keyin sahifadagi JavaScript faqat til=uz ni ko'radi. sessiya esa har so'rovda serverga ketadi, lekin JavaScript uchun u mavjud emas. DevTools'ning Cookies jadvalida uni ko'rasiz — HttpOnly ustunida belgisi bilan.

4.2 Nega bu himoya

Gap XSS'da. XSS (Cross-Site Scripting) — hujumchining skripti sizning sahifangiz ichida ishga tushib qolishi (Brauzer xotirasi va xavfsizlik modeli darsida ko'rgansiz). Saytga begona skript tushib qolsa, u sahifadagi hamma narsani o'qiydi — localStorage ni ham, document.cookie ni ham. Agar sessiya identifikatori o'qiladigan joyda bo'lsa, hujumchi uni o'z serveriga yuboradi va sizning nomingizdan kiradi. HttpOnly cookie'ni esa skript ko'rmaydi — o'g'irlashning iloji yo'q.

Bu to'liq himoya emas: begona skript sahifa ichida turib, siz nomingizdan so'rov yubora oladi (cookie o'zi qo'shiladi). Lekin u sessiyani olib ketolmaydi — sahifa yopilishi bilan uning imkoniyati tugaydi. XSS'ning o'zidan himoya — XSS va DOM xavfsizligi darsida.

5. Qiymatni kodlash

Cookie qiymatida ; bo'lishi mumkin emas — u atributlarni ajratadi. Bo'sh joy, vergul va kirill harflari ham muammo beradi. Sinab ko'ramiz:

html
<script>
  document.cookie = "izoh=Ko'k choy; 2 ta";
  console.log(document.cookie);

  document.cookie = "izoh=" + encodeURIComponent("Ko'k choy; 2 ta");
  console.log(document.cookie);
</script>

Konsolda:

text
izoh=Ko'k choy
izoh=Ko'k%20choy%3B%202%20ta

Birinchi urinishda ; 2 ta atribut deb tushunildi va qiymatdan kesib tashlandi. encodeURIComponent maxsus belgilarni % kodlariga aylantirdi (URL anatomiyasi darsidagi percent-encoding): bo'sh joy — %20, ; — %3B. O'qishda decodeURIComponent asl matnni qaytaradi — cookieniOl aynan shunday qiladi. Bu ikki funksiyani URL va URLSearchParams darsida to'liq ko'ramiz.

Maslahat: Murakkab ma'lumot (obyekt, ro'yxat) uchun cookie yaxshi joy emas. Bitta cookie'ning nomi va qiymati birgalikda ko'pi bilan 4096 bayt. Bundan tashqari, har cookie har so'rovda — hatto har rasm uchun ham — serverga ketadi. 4 KB × 50 so'rov = har sahifa ochilishida 200 KB ortiqcha trafik. Server bilishi shart bo'lmagan narsa — localStorage ga.

6.1 Zamonaviy, asinxron interfeys

document.cookie 1990-yillardan qolgan va noqulay: bitta satr, qo'lda bo'laklash, xato yozilsa — jim rad etish. Cookie Store API — uning zamonaviy o'rinbosari. U global cookieStore obyekti orqali ishlaydi va hamma metodi Promise qaytaradi (Promise asoslari), ya'ni sahifani kutib qoldirmaydi:

html
<script type="module">
  await cookieStore.set("til", "uz");
  await cookieStore.set({
    name: "savat",
    value: "3",
    expires: Date.now() + 60 * 60 * 1000,
  });

  const til = await cookieStore.get("til");
  console.log(til.name, til.value);

  const hammasi = await cookieStore.getAll();
  console.log(hammasi.map((c) => c.name));

  await cookieStore.delete("savat");
  console.log(document.cookie);
</script>

Konsolda:

text
til uz
(2) ['til', 'savat']
til=uz

type="module" — eng yuqori darajada await yozish uchun (Dinamik import() va top-level await). Farqlar:

  • get(nom) — tayyor obyekt: name, value, expires (ms yoki null), path, sameSite, secure va boshqalar. Topilmasa — null. Bo'laklash shart emas.
  • set — muddat expires da, millisekundda (Date.now() + necha ms).
  • delete(nom) — o'chirish metodi bor, Max-Age=0 hiylasi shart emas.
  • Xato yozilsa — jim rad etish emas, rad etilgan Promise (catch bilan ushlaysiz).
  • cookieStore.set dan yaratilgan cookie standart bo'yicha Secure va SameSite=Strict — xavfsizroq.

HttpOnly cookie bu API'da ham ko'rinmaydi — qoida o'zgarmaydi.

6.2 change hodisasi

cookieStore cookie o'zgarganini xabar ham qiladi — document.cookie da bunday imkon yo'q edi:

html
<script type="module">
  cookieStore.addEventListener("change", (event) => {
    for (const c of event.changed) {
      console.log("o'zgardi:", c.name, "=", c.value);
    }
    for (const c of event.deleted) {
      console.log("o'chdi:", c.name);
    }
  });

  await cookieStore.set("til", "en");
  await cookieStore.delete("til");
</script>

Konsolda:

text
o'zgardi: til = en
o'chdi: til

Hodisa boshqa tabdagi o'zgarishda ham, server yangi Set-Cookie yuborganda ham keladi. Chrome 154 da ikki tab bilan tekshirdik: server til va HttpOnly li sessiya ni berdi, hodisada esa faqat til keldi — HttpOnly cookie bu yerda ham ko'rinmaydi. Masalan, foydalanuvchi bir tabda tizimdan chiqsa, boshqa tab buni darhol sezadi.

6.3 Qayerda ishlaydi

web-features ma'lumotiga ko'ra cookieStore ning sahifadagi qismi (get, getAll, set, delete, change) 2025-yil iyundan beri hamma asosiy brauzerlarda bor: Chrome 87, Firefox 140, Safari 18.4. Bu "Baseline — yangi" (2025-06-24) holati. Eski brauzerlarni ham qo'llash kerak bo'lsa — document.cookie. Buni tekshirish oson: if ("cookieStore" in window) { ... }.

7. Token qayerda saqlanadi

Autentifikatsiyali so'rovlar darsida kirishToken bilan ishlagansiz. Brauzerda tokenni saqlashning uchta yo'li bor. Har birining narxi bor. Jadvaldagi CSRF (Cross-Site Request Forgery) — begona sayt sizning brauzeringiz orqali, cookie'laringiz bilan so'rov yuborishi; "Hujumchi nigohi" bo'limida misolini ko'ramiz.

Joy XSS o'qiy oladimi CSRF xavfi Sahifa yangilansa
localStorage Ha — to'liq Yo'q Qoladi
JS o'zgaruvchisi (xotira) Faqat sahifa ochiq turganda Yo'q Yo'qoladi
HttpOnly cookie Yo'q Bor (SameSite kamaytiradi) Qoladi

Real loyihalarda ko'p uchraydigan yechim:

  • Uzoq muddatli yangilash tokeni (refresh token) — HttpOnly; Secure; SameSite=Strict cookie'da. JavaScript uni hech qachon ko'rmaydi.
  • Qisqa muddatli kirish tokeni (5–15 daqiqa) — faqat JS o'zgaruvchisida. Sahifa yangilansa, cookie yordamida server'dan yangisi olinadi.

Bunda XSS hatto ishga tushsa ham, uzoq muddatli tokenni o'g'irlay olmaydi. Server tomoni (cookie'ni o'rnatish, CSRF tokenlari) — backend qismida (Cookie chuqur).

Diqqat: "Token localStorage da — xavfli, cookie'da — xavfsiz" degan gap to'liq emas. Cookie'da bo'lsa ham, HttpOnly siz yozilsa — document.cookie dan o'qiladi va localStorage dan farqi qolmaydi. Himoyani HttpOnly beradi, "cookie" so'zi emas.

Hujumchi nigohi

1-hujum — XSS orqali o'g'irlash. Saytga tushgan begona skript document.cookie ni o'qib, o'z serveriga yuboradi. Himoya: sessiya va token cookie'lari — faqat HttpOnly. JavaScript'ga kerak bo'lgan cookie'ga (til, tema) maxfiy narsa yozilmaydi.

2-hujum — CSRF (begona sayt nomidan so'rov). Dilshod aka «Bahor» saytiga kirgan. Keyin u begona saytni ochadi. U yerda yashirin forma https://example.com/bron/bekor ga POST yuboradi. Brauzer so'rovga «Bahor» cookie'larini o'zi qo'shsa, server buni Dilshod akaning o'zi bosgan deb o'ylaydi. Himoya: sessiya cookie'si SameSite=Lax yoki Strict — begona saytdan boshlangan POST ga cookie qo'shilmaydi. Muhim amallarda server qo'shimcha CSRF tokenini ham tekshiradi (Brauzer xavfsizlik modeli).

3-hujum — ochiq tarmoqda tinglash. Kafe Wi-Fi'ida HTTP so'rovdagi cookie'ni yo'lda o'qish mumkin. Himoya: Secure — cookie faqat HTTPS'da yuboriladi. Ishonchliroq yo'li — nomi __Host- bilan boshlanadigan cookie: brauzer uni faqat Secure va Path=/ bilan, Domain siz qabul qiladi, aks holda rad etadi (Chrome 154 da tekshirildi).

8. Ko'p uchraydigan xatolar

document.cookie = "" cookie'larni tozalamaydi — u hech narsa qilmaydi. Tuzatish: har cookie'ni alohida, Max-Age=0 va to'g'ri Path bilan o'chiring yoki cookieStore.delete.

8.2 Qiymatni kodlamaslik

;, bo'sh joy yoki kirill harfli qiymat kesilib qoladi yoki serverda buziladi. Tuzatish: yozishda encodeURIComponent, o'qishda decodeURIComponent.

8.3 SameSite=None ni Secure siz yozish

Cookie jim yo'qoladi — xato ham chiqmaydi. Tuzatish: None faqat Secure bilan. Umuman, None kerak bo'lishi kam: u faqat boshqa sayt ichidagi iframe yoki vidjet uchun.

8.4 HttpOnly ni JavaScript'dan qo'yishga urinish

document.cookie = "sessiya=...; HttpOnly" — cookie umuman yaratilmaydi. Tuzatish: bunday cookie'ni server Set-Cookie bilan beradi; JavaScript'ning ishi — so'rov yuborish, xolos.

9. Mashqlar

1-mashq (oson): cookieniYoz funksiyasi

cookieniYoz(nom, qiymat, kun) funksiyasini yozing. U qiymatni kodlab, Path=/, SameSite=Lax va kun kunlik Max-Age bilan cookie yozsin. kun berilmasa — sessiya cookie'si bo'lsin. Darsdagi cookieniOl bilan tekshiring: cookieniYoz("ism", "Dilshod aka", 30) dan keyin cookieniOl("ism") — Dilshod aka.

Ishora: bir kunda 86 400 soniya; Max-Age qismini faqat kun !== undefined bo'lsa qo'shing.

Yechim
html
<script>
  function cookieniYoz(nom, qiymat, kun) {
    let satr = `${nom}=${encodeURIComponent(qiymat)}; Path=/`;
    satr += "; SameSite=Lax";
    if (kun !== undefined) {
      satr += `; Max-Age=${kun * 86400}`;
    }
    document.cookie = satr;
  }

  function cookieniOl(nom) {
    for (const juft of document.cookie.split("; ")) {
      const belgi = juft.indexOf("=");
      if (juft.slice(0, belgi) === nom) {
        return decodeURIComponent(juft.slice(belgi + 1));
      }
    }
    return null;
  }

  cookieniYoz("ism", "Dilshod aka", 30);
  cookieniYoz("vaqtincha", "1");
  console.log(cookieniOl("ism"));
  console.log(document.cookie);
</script>

Konsolda:

text
Dilshod aka
ism=Dilshod%20aka; vaqtincha=1

document.cookie da faqat nom va qiymat ko'rinadi — atributlar (Path, Max-Age) o'qishda qaytmaydi. Ularni faqat DevTools'ning Cookies jadvalida ko'rasiz.

Ko'p saytlarda pastda "Sayt cookie ishlatadi — Roziman" paneli chiqadi. Shunday panel yasang: «Roziman» bosilsa, rozilik=1 cookie'si 180 kunga yozilsin va panel yashirilsin. Sahifa qayta ochilganda cookie bo'lsa — panel umuman ko'rinmasin. Konsolga holatni chiqaring.

Ishora: panelni boshida hidden qiling va faqat cookie yo'q bo'lsa oching — shunda panel "yonib-o'chmaydi".

Yechim
html
<style>
  #panel { position: fixed; inset: auto 0 0; padding: 0.8rem;
    background: #1f3d2b; color: #fff; font: 1rem system-ui; }
</style>
<p>«Bahor» menyusi</p>
<div id="panel" hidden>
  Sayt tilni eslab qolish uchun cookie ishlatadi.
  <button id="roziman" type="button">Roziman</button>
</div>
<script>
  const panel = document.getElementById("panel");
  const rozimi = document.cookie
    .split("; ")
    .includes("rozilik=1");

  console.log(rozimi ? "Rozilik bor" : "Rozilik so'raladi");
  panel.hidden = rozimi;

  document.getElementById("roziman").addEventListener("click", () => {
    const muddat = 180 * 86400;
    document.cookie = `rozilik=1; Max-Age=${muddat}; Path=/`;
    panel.hidden = true;
    console.log("Rozilik saqlandi");
  });
</script>

Konsolda:

text
Rozilik so'raladi

«Roziman» ni bosib, qayta ishga tushirsangiz — panel chiqmaydi, konsolda Rozilik bor. Bu yerda split("; ").includes(...) yetarli: biz aniq juftlikni qidiryapmiz, qiymatni o'qish shart emas.

Haqiqiy loyihada qonun talablari bor (Yevropada GDPR): reklama va analitika cookie'lari rozilikdan keyin yoziladi. Til yoki sessiya kabi zarur cookie'larga rozilik shart emas.

cookieStore bilan ikki funksiya yozing:

  1. kukilarRoyxati() — hamma cookie'ni {nom: qiymat} obyekti qilib qaytarsin (Promise).
  2. hammasiniOchir() — hamma cookie'ni o'chirsin va nechta o'chirilganini qaytarsin.

Sinov: til, tema, savat yozing, ro'yxatni chiqaring, hammasini o'chiring, ro'yxatni yana chiqaring. Ishora: getAll() massiv beradi — Object.fromEntries uchun [nom, qiymat] juftlari kerak; o'chirishni Promise.all bilan parallel qiling (Promise kombinatorlari).

Yechim
html
<script type="module">
  async function kukilarRoyxati() {
    const hammasi = await cookieStore.getAll();
    return Object.fromEntries(hammasi.map((c) => [c.name, c.value]));
  }

  async function hammasiniOchir() {
    const hammasi = await cookieStore.getAll();
    await Promise.all(hammasi.map((c) => cookieStore.delete(c.name)));
    return hammasi.length;
  }

  await cookieStore.set("til", "uz");
  await cookieStore.set("tema", "qorongi");
  await cookieStore.set("savat", "3");
  console.log(await kukilarRoyxati());
  console.log("O'chirildi:", await hammasiniOchir());
  console.log(await kukilarRoyxati());
</script>

Konsolda:

text
{til: 'uz', tema: 'qorongi', savat: '3'}
O'chirildi: 3
{}

hammasiniOchir faqat JavaScript ko'radigan cookie'larni o'chiradi. HttpOnly sessiya cookie'si qoladi — shuning uchun haqiqiy "Chiqish" tugmasi serverga so'rov yuboradi va server Set-Cookie: sessiya=; Max-Age=0 bilan o'zi o'chiradi.

Faylni kurs/mashqlar/11/27-cookie/index.html ga saqlang:

bash
git add 11/27-cookie/index.html
git commit -m "11/27: cookieStore bilan cookie ro'yxati va tozalash"

vazifalar da bu darsga qadam yo'q: ilova ma'lumotini server bilmaydi va unga cookie kerak emas. U 11-qism oxirida serverga ulanganda ham kalit localStorage da turadi.

10. Real ishda

  • Kirish (login). Deyarli hamma sayt sessiyani HttpOnly; Secure; SameSite cookie'da ushlaydi. Frontend dasturchining vazifasi — fetch da credentials ni to'g'ri qo'yish (Request, Response, Headers va fetch opsiyalari) va hech qachon tokenni document.cookie ga yozmaslik.
  • Til va region. Server sahifani to'g'ri tilda tayyorlashi uchun til=uz kabi oddiy cookie — 1-mashqdagi cookieniYoz aynan shu.
  • Rozilik bannerlari. Rozilik vositalari (CMP) tanlovni cookie'da saqlaydi va analitika skriptlarini faqat rozilikdan keyin yuklaydi.
  • Kutubxonalar. js-cookie — document.cookie ustidagi kichik o'ram (Cookies.get("til")). Yangi loyihada cookieStore ko'pincha uning o'rnini bosadi.
  • Intervyu. "HttpOnly, Secure, SameSite nima?", "Token qayerda saqlanadi?", "CSRF nima va SameSite qanday himoya qiladi?" — deyarli har frontend va full-stack intervyuda.

Xulosa

  • document.cookie ga yozish — bitta cookie qo'shadi yoki yangilaydi; o'qish — hammasini "a=1; b=2" satrida beradi.
  • Muddat — Max-Age (soniya); o'chirish — xuddi shu nom, Path va Domain bilan Max-Age=0. Chrome muddatni 400 kun bilan cheklaydi.
  • Path, Domain — kim ko'radi; Secure — faqat HTTPS; SameSite — begona saytdan boshlangan so'rovga qo'shiladimi.
  • HttpOnly cookie'ni faqat server qo'yadi va JavaScript uni ko'rmaydi — sessiya va tokenlar uchun eng xavfsiz joy.
  • cookieStore — asinxron, qulay API va change hodisasi; 2025 dan beri hamma asosiy brauzerlarda.

Keyingi dars: IndexedDB va brauzer xotira kvotasi — megabaytlab ma'lumot, obyektlar va qidiruv uchun brauzer ichidagi haqiqiy ma'lumotlar bazasi.

Manbalar

  • RFC 6265 va uning yangilanishi (RFC 6265bis): "HTTP State Management Mechanism" — ietf.org
  • MDN: "Document: cookie property", "Using HTTP cookies", "Cookie Store API" — developer.mozilla.org
  • web.dev: "SameSite cookies explained" — web.dev
  • OWASP: "Cross-Site Request Forgery Prevention Cheat Sheet" — cheatsheetseries.owasp.org
Ulashish:Telegram'da

Izohlar (0)

Izoh yozish uchun kiring.

  • Hozircha izoh yo'q. Birinchi bo'ling!
Cookie'lar JavaScript'dan: document.cookie, atributlar va Cookie Store API — IlmHamroh