CORS алдааг хэрхэн засах вэ (мөн яагаад гардаг вэ)
CORS алдаа гэдэг нь таны вэб хуудас өөр origin (өөр домэйн, порт эсвэл протокол)-ээс хариу унших гэсэн боловч тэр сервер зөвшөөрснийг заасан header илгээгээгүйг хэлнэ. Хөтөч хэрэглэгчийг хамгаалахын тулд хариуг блоклодог. Засвар нь серверт байна: сайтын origin-д Access-Control-Allow-Origin header буцааж, OPTIONS preflight хүсэлтийг зохицуулах, эсвэл хүсэлтийг өөрийн backend-ээр, ижил origin-ээр дамжуулж зайлсхийх.
Энэ нь вэб хөгжүүлэлтийн хамгийн будилуулдаг алдааны нэг, учир нь хүсэлт ихэвчлэн серверт зөв хүрдэг. Энэ гарын авлага юу болж байгааг, хувилбар бүрийг хэрхэн засахыг тайлбарлана.
“Origin” гэдэг нь юу вэ
Origin нь протокол, домэйн, портын хослол:
| URL | Origin |
|---|---|
https://myapp.com/dashboard | https://myapp.com |
https://api.myapp.com/users | https://api.myapp.com (өөр дэд домэйн, тиймээс өөр origin) |
http://localhost:5173 | http://localhost:5173 |
http://localhost:3000 | http://localhost:3000 (өөр порт, тиймээс өөр origin) |
Хөтчүүд same-origin policy дагадаг: хуудасны JavaScript өөрийн origin-ийн хариуг чөлөөтэй уншина, харин бусдынхыг уншиж чадахгүй. CORS (Cross-Origin Resource Sharing) нь серверт сонголт өгөх систем юм: “миний хариуг эдгээр origin-ийн хуудсууд уншиж болно.”
Хоёр зүйл хүмүүсийг гайхшруулдаг:
- Хүсэлт ихэвчлэн серверт хүрдэг. CORS ихэвчлэн таны кодыг хариуг уншихаас хаадаг, серверийг хүсэлт хүлээн авахаас биш. POST хадгалагдсан байж болох ч та алдаа харсан байж болно.
- Зөвхөн хөтөч хэрэгжүүлдэг. curl, Postman болон серверийн код CORS-ийг огт үл тооцдог. Тиймээс “Postman дээр ажилладаг” гэдэг нь CORS-ийн талаар юу ч хэлэхгүй.
Алхам 1: Яг алдааг унших
Developer tools нээ (хулганы баруун товч → Inspect), Console руу орж бүтэн мессежийг унш. Chrome-ийн үг хэллэг нь ямар асуудалтай байгааг заана:
| Мессеж агуулсан | Юу буруу байна |
|---|---|
No 'Access-Control-Allow-Origin' header is present | Сервер header огт илгээгээгүй, эсвэл хүсэлт CORS кодонд хүрэхээс өмнө бүтэлгүйтсэн (жишээ нь 404 эсвэл 500) |
The 'Access-Control-Allow-Origin' header has a value '...' that is not equal to the supplied origin | Сервер таны origin-оос өөр origin-ийг зөвшөөрч байна |
Response to preflight request doesn't pass access control check | OPTIONS preflight бүтэлгүйтсэн |
...must not be the wildcard '*' when the request's credentials mode is 'include' | Та cookie илгээж байгаа, сервер * буцаасан |
Request header field authorization is not allowed | Сервер тэр header-ийг Access-Control-Allow-Headers-т жагсаагаагүй |
Дараа нь Network таб нээж, бүтэлгүйтсэн хүсэлтийг (мөн түүний өмнөх OPTIONS хүсэлтийг) олж, статус код ба хариуны header-үүдийг хар.
Эхлээд статус кодыг шалга. Олон “CORS алдаа” бол жинхэнэ серверийн алдааг нуусан байдаг. Сервер унах эсвэл 404 буцаавал түүний алдааны хариунд ихэвчлэн CORS header байдаггүй, тиймээс хөтөч жинхэнэ асуудлын оронд CORS гэж мэдэгддэг. 500 эсвэл 404-ийг засаарай, CORS алдаа алга болж магадгүй.
Алхам 2: Энэ API-г хөтчөөс огт дуудах эсэхээ шийд
Header нэмэхээсээ өмнө асуу: хөтөч энэ API-г шууд дуудах ёстой юу?
- Нууц түлхүүр шаардлагатай гуравдагч талын API (OpenAI, Stripe-ийн нууц түлхүүр, ихэнх имэйлийн үйлчилгээ) хөтчөөс хэзээ ч дуудагдах ёсгүй. Түлхүүр бүх зочинд харагдана. Backend-ээсээ дуудаарай, тэгвэл CORS асуудал арилна, учир нь сервер-сервер хүсэлт CORS-д хамаардаггүй. API түлхүүрээ аюулгүй байлгах нь харна уу.
- Таны хянадаггүй гуравдагч талын API CORS header илгээдэггүй бол таны талаас засах боломжгүй. Backend-ээсээ дуудаарай.
- Өөрийн API зөв тохируулснаар засагдана. Доор үргэлжлүүл.
Алхам 3: Серверийн дээр засах
Сервер хариу бүрт, алдааны хариунд ч гэсэн зөв header нэмэх ёстой.
Жинхэнэ хүсэлтэд дараахыг илгээ:
Access-Control-Allow-Origin: https://myapp.com(таны front end-ийн яг origin, сүүлд слэшгүй)Vary: Origin, хэрэв утга нь аль origin асуусанаас хамаарвал
Preflight OPTIONS хүсэлтэд амжилтын статус (200 эсвэл 204) болон дараахыг буцаа:
Access-Control-Allow-Origin: https://myapp.comAccess-Control-Allow-Methods: GET, POST, PUT, PATCH, DELETEAccess-Control-Allow-Headers: Content-Type, Authorization(илгээдэг захиалгат header бүр)- Сонголтоор
Access-Control-Max-Age: 600, хөтөч preflight-ийг хэсэг хугацаанд кэшлэх
Ихэнх framework-д үүнийг хийдэг багц эсвэл тохиргоо байдаг. Express-д cors багц; FastAPI-д CORSMiddleware; ASP.NET Core-д AddCors; Spring-д @CrossOrigin эсвэл CORS тохиргоо. Express-ийн ердийн тохиргоо:
import cors from "cors";
app.use(cors({
origin: ["https://myapp.com", "http://localhost:5173"],
credentials: true,
}));
CORS зохицуулалтыг маршрут болон нэвтрэлтээс өмнө тавь, ингэснээр нэвтрэлтгүй preflight хүсэлт 401-ээр огцом бүтэлгүйтэхгүй.
AI builder ашиглаж байгаа бол тохиргоог яг тодорхойл:
https://myapp.comдээрх front end ньhttps://api.myapp.comAPI-г дуудаж байгаа бөгөөд “Response to preflight request doesn't pass access control check” гарч байна. API дээр CORS-ийг ягhttps://myapp.comболон preview origin-д зөвшөөрөхөөр тохируул, GET, POST, PATCH, DELETE-ийг Content-Type ба Authorization header-тэй зөвшөөр, OPTIONS-ийг нэвтрэлтээс өмнө зохицуул, алдааны хариунд ч CORS header нэм.
Алхам 4: Cookie болон credentials-ийг зохицуул
Front end нь өөр origin руу cookie (жишээ нь нэвтрэлтийн session) илгээж байгаа бол хоёр тал тохирох ёстой:
- Front end нь
fetchдээрcredentials: "include", эсвэл axios дээрwithCredentials: trueтавина. - Сервер
Access-Control-Allow-Credentials: trueилгээнэ. - Серверийн
Access-Control-Allow-Originнь*биш, яг origin байх ёстой.
Cross-site cookie нь мөн SameSite=None; Secure шаарддаг, мөн зарим хөтөч гуравдагч талын cookie-г илүү хязгаарладаг. Энэ нь Алхам 5-ын арга барилыг илүү сонгох нэмэлт шалтгаан.
Алхам 5: Same-origin тохиргоогоор CORS-ээс зайлсхий
Ихэвчлэн хамгийн цэвэр засвар бол огт cross-origin хүсэлт гаргахгүй байх. API-г хуудастай ижил origin дээр үйлчил, жишээ нь https://myapp.com/api/...:
- Хөгжүүлэлтэд ихэнх dev server proxy хийж чадна. Vite-ийн
server.proxyтохиргоо/api-г өөр порт дээрх backend руу дамжуулж, хөтөч зөвхөн нэг origin-тэй харьцана. - Production-д
/api-г хостын rewrite эсвэл proxy тохиргоогоор backend руу чиглүүлэх, эсвэл front end болон API-г нэг серверээс үйлчлэх.
Front end дараа нь fetch("/api/orders") гэх харьцангуй замыг дуудна. Origin хоорондын хүсэлт, origin хоорондын preflight, cookie-ийн толгойны асуудал байхгүй. Мөн preview болон production-ын хооронд ялгаатай API домэйн кодлох шаардлагагүй болно.
Front end-ийг бүтэн URL-ийн оронд харьцангуй /api замаар backend-ээ дуудуул, /api-г API сервер рүү дамжуулах dev proxy тохируул. Дараа нь хэрэггүй болсон CORS тохиргоог бүгдийг нь хас.
Юу хийж болохгүй вэ
fetch-ийнmode: "no-cors". Ямар ч зүйлийг тойрдоггүй; таны кодонд хоосон, уншигдахгүй хариу өгдөг.- CORS-ийг идэвхгүй болгодог browser extension. Тэд зөвхөн таны хөтчийг өөрчилдөг. Бүх зочин алдааг хэвээр харна.
- Бодит аппад зориулсан нийтийн “CORS proxy” үйлчилгээ. Тэд дамжиж буй бүх зүйлийг унших, өөрчлөх боломжтой, мөн унадаг.
- Нэвтрэлттэй API дээр
Access-Control-Allow-Origin: *. Credentials-тай хамт ажилладаггүй, хувийн өгөгдлийн хувьд буруу өгөгдмөл. - Ямар ч
Originheader-ийг буцаан тусгах, credentials зөвшөөрсөн тохиолдолд. Энэ нь ямар ч вэбсайтад хэрэглэгчдийнхээ өмнөөс нэвтэрсэн хүсэлт гаргах боломж өгдөг. Зөвшөөрлийн жагсаалт ашигла.
AI-аар бүтээсэн аппуудын түгээмэл шалтгаанууд
| Нөхцөл байдал | Засвар |
|---|---|
| Front end нь нууц түлхүүртэй гуравдагч талын API-г дуудна | Дуудлагыг backend руу зөө |
| Preview дээр ажилладаг, нийтлэгдсэн домэйн дээр бүтэлгүйтдэг | Нийтлэгдсэн болон захиалгат домэйн origin-уудыг зөвшөөрлийн жагсаалтад нэм, эсвэл харьцангуй /api замыг ашигла |
| Зөвхөн POST, PUT эсвэл DELETE дээр алдаа | Preflight зохицуулагдаагүй; OPTIONS болон зөвшөөрөгдсөн header-ийг нэм |
| Нэвтрэлт нэмсний дараа алдаа гарсан | Credentials нь яг origin, Allow-Credentials шаарддаг |
| “CORS алдаа” гэвч Network таб 500 харуулж байна | Эхлээд серверийн алдааг засах |
API хаяг localhost-д хатуу кодлогдсон | Харьцангуй зам эсвэл орчин бүрийн тохиргоо ашигла |
Mythex дэх CORS
Mythex төсөлд вэбсайт болон API сервер хоёулаа нэг төсөлд үйлчилгээ хэлбэрээр ажиллаж, preview дотор хооронд нь сольж болно. Агентаас front end-ийг backend-ээ харьцангуй /api замаар дуудуулах, хөгжүүлэлтэд proxy хийлгэх нь ихэнх CORS асуудлаас зайлсхийдэг. Хэрэв эх origin-ууд хоорондоо дуудах шаардлагатай бол агентад консолын яг алдаа болон оролцсон origin-уудыг өг. Нийтлэгдсэн аппын хаяг preview-ээс өөр тул үр дүнг нийтлэгдсэн аппад бас шалга. Харна уу: баримт бичгийн Олон үйлчилгээтэй апп болон API backend, мөн AI-аар бүтээсэн аппыг дебаг хийх болон frontend ба backend гарын авлагууд.
CORS хяналтын жагсаалт
- Бүтэн console алдаа болон бүтэлгүйтсэн хүсэлтийн статус кодыг уншсан
- Нуугдсан 404 эсвэл 500-г үгүйсгэсэн
- Нууц түлхүүртэй API-г хөтчөөс биш backend-ээс дуудаж байгаа
- Сервер
Access-Control-Allow-Origin-г яг зөвшөөрөгдсөн origin-оор илгээж байгаа -
OPTIONSpreflight зөвшөөрөгдсөн арга, header-ээр нэвтрэлтээс өмнө хариулдаг - CORS header алдааны хариунд ч байгаа
- Credentials: яг origin,
Allow-Credentials: true, зөв cookie тохиргоо - Preview, нийтлэгдсэн болон захиалгат домэйн origin бүгд хамрагдсан, эсвэл харьцангуй
/apiзам ашиглагдсан -
no-cors, нийтийн proxy, origin-ийг буцаан тусгах товчлолууд байхгүй
Асуултууд
CORS алдаа гэж юу гэсэн үг вэ?
Таны хуудас нэг origin-оос ачаалагдаж, өөр origin-ийн хариуг унших гэсэн боловч тэр серверийн хариунд унших зөвшөөрөл өгөх header байхгүй байсан. Хөтөч таны кодыг хариуг уншихаас хаадаг. Засвар нь серверт эсвэл хүсэлтийн чиглүүлэлтэд байдаг, front end кодонд биш.
Front end-ээс CORS алдааг засаж болох уу?
Зөв биш. mode: 'no-cors' гэх мэт тохиргоо зөвхөн хариуг таны кодоос нуудаг. Серверийг зөв Access-Control-Allow-Origin header илгээлгэх, эсвэл API-г өөрийн backend эсвэл same-origin proxy-р дуудах замаар засдаг.
Access-Control-Allow-Origin: * аюулгүй юу?
Хэн ч уншиж болох нийтийн мэдээлэлд, жишээ нь нэвтрэлтгүй нийтийн API-д зүйтэй. Cookie эсвэл бусад credentials-тэй хамт ашиглах боломжгүй, хувийн API-д зөвшөөрөгдсөн origin-уудыг яг жагсаах хэрэгтэй.
Яагаад хүсэлт Postman эсвэл curl дээр ажилладаг ч хөтөч дээр ажиллахгүй вэ?
CORS-ийг зөвхөн хөтөч хэрэгжүүлдэг. Postman, curl зэрэг хэрэгсэл үүнийг хэрэглэдэггүй тул хүсэлт тэнд амжилттай болоод, хуудасны JavaScript гаргахад блоклогдож болно.
Preflight хүсэлт гэж юу вэ?
Энгийн биш хүсэлтүүдэд, жишээ нь JSON POST эсвэл Authorization header-тэй хүсэлтэд, хөтөч эхлээд OPTIONS хүсэлт илгээж ямар арга, header зөвшөөрөгдсөнийг серверээс асуудаг. Хэрэв тэр OPTIONS хүсэлт бүтэлгүйтвэл эсвэл зөв header байхгүй бол жинхэнэ хүсэлт огт илгээгдэхгүй.