Maqolalar 5 daqiqa 352 ko‘rish
CORS: brauzer aslida nimadan himoya qilyapti
CORS xatosi deyarli har bir dasturchining jig‘iga tekkan, lekin ko‘pchilik uni noto‘g‘ri tushunadi va StackOverflow'dan «allow all» ni ko‘chirib, o‘ziga eshik ochib qo‘yadi. Same-Origin Policy, preflight so‘rov va Django'da to‘g‘ri sozlashni tartib bilan ko‘ramiz.
Mundarija
Bu manzara deyarli har bir jamoada takrorlanadi. Frontendchi kelib aytadi:
"API'ing ishlamayapti, CORS xatosi beryapti". Backendchi shoshib
StackOverflow'ni ochadi, birinchi topilgan javobni — CORS_ALLOW_ALL_ORIGINS
= True — ko‘chiradi, xato yo‘qoladi va hamma xursand tarqaladi. Faqat bir
narsa e'tibordan chetda qoladi: endi internetdagi istalgan sayt sizning
API'ingizga foydalanuvchi nomidan so‘rov yubora oladi.
CORS shu qadar ko‘p jig‘iga tekkan mavzu bo‘lgani uchun uni bir marta chindan tushunib olishga arziydi. Chunki muammo aslida CORS'da emas, uni noto‘g‘ri tushunishda.
Avval Same-Origin Policy#
Hammasi brauzerdagi bitta qattiq qoidadan boshlanadi: bir saytda ishlab turgan JavaScript boshqa "origin"ga so‘rov yuborib, uning javobini o‘qiy olmaydi. Origin bu yerda protokol, domen va portning yig‘indisi:
https://solijonov.uz va https://api.solijonov.uz → har xil origin
https://solijonov.uz va https://solijonov.uz:8000 → har xil origin
Bu qoida nega borligini bitta misol bilan tushunish oson. Aytaylik, siz bankingizga kirib turibsiz, sessiyangiz brauzerda ochiq. Boshqa tabda esa tasodifan yomon niyatli sayt ochilgan. Agar bu qoida bo‘lmasa, o‘sha yomon sayt o‘z JavaScript'i bilan bankingizning manziliga so‘rov yuborar va sizning sessiyangiz bilan javobni — masalan hisob balansini — o‘qib olardi. Same-Origin Policy aynan shuni to‘xtatadi. Ya'ni bu qoida sizga xalaqit berish uchun emas, sizni himoya qilish uchun bor.
Endi eng muhim jumla: CORS himoya emas, u himoyani nazorat ostida yumshatish usuli. Ya'ni "mening API'imga aynan mana bu origin'lardan so‘rov yuborishga ruxsat" deb aytishning yo‘li.
CORS qanday ishlaydi#
Brauzer boshqa origin'ga so‘rov yuborayotganda serverdan "ruxsatnoma" so‘raydi. Oddiy so‘rovda u javobning sarlavhasiga qaraydi:
Access-Control-Allow-Origin: https://solijonov.uz
Agar javobdagi bu sarlavhada so‘rov yuborgan origin ko‘rsatilgan bo‘lsa, brauzer JavaScript'ga javobni o‘qishga ruxsat beradi. Bo‘lmasa — javob serverdan muvaffaqiyatli kelgan bo‘lsa ham, brauzer uni JavaScript'dan yashiradi va konsolda o‘sha tanish CORS xatosini ko‘rsatadi.
Ba'zi so‘rovlarda esa qo‘shimcha bosqich bor. Masalan Content-Type:
application/json bilan yuborilgan POST so‘rovdan oldin brauzer avval
"razvedka" yuboradi — bu OPTIONS metodli preflight so‘rov. U serverdan
"shu origin'dan, shu metod bilan kelsam bo‘ladimi?" deb so‘raydi. Server
ruxsat beruvchi sarlavhalar bilan javob bersa, shundan keyingina asosiy
so‘rov ketadi.
Bu yerda bir narsa chalg‘itadi: preflight'ga 200 kelishining o‘zi
"ruxsat berildi" degani emas. Sinovda ro‘yxatda yo‘q origin'dan kelgan
OPTIONS so‘rov ham 200 oldi — faqat javobda birorta Access-Control-*
sarlavhasi bo‘lmadi, va brauzer asosiy so‘rovni yubormaydi. Shuning uchun
CORS muammosini tekshirayotganda status kodga emas, javob sarlavhalariga
qarang.
Ikki eng keng tarqalgan tushunmovchilik#
Birinchisi: "CORS server himoyasi". Yo‘q. CORS faqat brauzerdagi JavaScript'ni cheklaydi. curl, Postman yoki boshqa serverdan yuborilgan so‘rovga CORS umuman ta'sir qilmaydi — ular bemalol o‘tadi. Ya'ni CORS API'ingizni himoya qilmaydi, real himoya boshqa narsalarda: autentifikatsiya, ruxsatlar, rate limiting.
Ikkinchisi: "hammaga ruxsat bersam nima bo‘ladi?". Access-Control-Allow-Origin:
* ochiq, cookie ishlatmaydigan API uchun — masalan ochiq ma'lumot beradigan
API uchun — mutlaqo normal. Lekin cookie yoki sessiya bilan ishlaydigan
API'da yulduzcha qo‘ysangiz, boshqa har qanday saytga foydalanuvchi sessiyasi
bilan so‘rov o‘qishga eshik ochasiz. Brauzerlar buni shu qadar xavfli deb
biladiki, "hammaga ruxsat" va "cookie bilan" birikmasini umuman bloklaydi.
Uni chetlab o‘tish uchun har kelgan origin'ni ko‘r-ko‘rona qaytarib qo‘yish
esa — bor xavfning eng yomon ko‘rinishi. Va bu "chetlab o‘tish" ba'zan
o‘z-o‘zidan sodir bo‘ladi: pastdagi Django misolida buni sinab ko‘rsatamiz.
Django'da to‘g‘ri sozlash#
Amalda django-cors-headers ishlatiladi:
INSTALLED_APPS = [..., "corsheaders"]
MIDDLEWARE = ["corsheaders.middleware.CorsMiddleware", ...] # ro'yxatda tepada tursin
# Aniq ro'yxat — yulduzcha emas:
CORS_ALLOWED_ORIGINS = [
"https://solijonov.uz",
"https://app.solijonov.uz",
]
CORS_ALLOW_CREDENTIALS = True # faqat cookie/sessiya kerak bo'lgan holatda
Qoida oddiy: ruxsat ro‘yxatida faqat siz ishonadigan real originlar tursin.
Development uchun http://localhost:5173 kabi manzillarni ham qo‘shasiz,
lekin uni kodga emas, muhit o‘zgaruvchisiga chiqarish ma'qul — production'da
o‘sha lokal manzillar ro‘yxatda qolib ketmaydi.
Sozlashda ikkita jimgina tuzoq bor, ikkalasini ham sinab ko‘rdim.
Birinchisi — CORS_ALLOW_ALL_ORIGINS va CORS_ALLOW_CREDENTIALS birga.
Brauzer "hammaga ruxsat + cookie" birikmasini bloklashini bilgan kutubxona
bu holatda yulduzcha o‘rniga kelgan origin'ning o‘zini qaytaradi.
Sinovda https://hujumchi.example dan yuborilgan so‘rov javobida shunday
sarlavhalar keldi:
Access-Control-Allow-Origin: https://hujumchi.example
Access-Control-Allow-Credentials: true
Ya'ni brauzer bloklaydigan narsa emas, undan ham kengrog‘i: istalgan sayt foydalanuvchi sessiyasi bilan so‘rov yuborib, javobini o‘qiy oladi. Hech qanday xato ham chiqmaydi — shuning uchun bu sozlama juftligi eng xavflisi. Aniq ro‘yxat bilan esa o‘sha begona origin javobida birorta CORS sarlavhasi bo‘lmadi.
Ikkinchisi — middleware tartibi. CorsMiddleware ro‘yxatda
CommonMiddleware dan pastda tursa, u yaratgan javoblarga sarlavha
qo‘shilmay qoladi. Sinovda oxiriga slash qo‘yilmagan /ping manziliga
kelgan so‘rov 301 bilan qaytdi va o‘sha javobda CORS sarlavhasi umuman
bo‘lmadi — /ping/ esa joyida ishladi. Frontend uchun bu "ba'zi manzillarda
CORS xatosi chiqadi, ba'zilarida yo‘q" degan chalkash manzara beradi.
Yodda qoladigan xulosa#
CORS'ni bir jumlaga siqish mumkin: Same-Origin Policy foydalanuvchini himoya qiladi, CORS esa siz o‘sha himoyada ongli ravishda ochadigan nazoratli eshik. Shuni tushunsangiz, "CORS xatosi" endi "API buzilgan" degan xavotir emas, "server bu origin'ga ruxsat bermagan" degan aniq xabar bo‘lib qoladi. Va "hammaga ruxsat + cookie" birikmasini hech qachon yozmang.