Kā novērst CORS kļūdas (un kāpēc tās rodas)
CORS kļūda nozīmē, ka tava tīmekļa lapa mēģināja nolasīt atbildi no citas izcelsmes (cita domēna, porta vai protokola), un šis serveris nenosūtīja galvenes, kas to atļauj. Pārlūki bloķē atbildi, lai aizsargātu lietotājus. Labojums ir serverī: atgriez galveni Access-Control-Allow-Origin savas vietnes izcelsmei un apstrādā OPTIONS preflight pieprasījumus. Alternatīvi to var izvairīties, sūtot pieprasījumu caur savu backend tajā pašā izcelsmē.
Tā ir viena no mulsinošākajām kļūdām tīmekļa izstrādē, jo pieprasījums bieži sasniedz serveri normāli. Šis ceļvedis izskaidro, kas notiek, un kā novērst katru variantu.
Ko nozīmē „izcelsme”
Izcelsme ir protokola, domēna un porta kombinācija:
| URL | Izcelsme |
|---|---|
https://myapp.com/dashboard | https://myapp.com |
https://api.myapp.com/users | https://api.myapp.com (cits apakšdomēns, tātad cita izcelsme) |
http://localhost:5173 | http://localhost:5173 |
http://localhost:3000 | http://localhost:3000 (cits ports, tātad cita izcelsme) |
Pārlūki ievēro vienas izcelsmes politiku: lapas JavaScript var brīvi lasīt atbildes no savas izcelsmes, bet ne no citām. CORS (Cross-Origin Resource Sharing) ir sistēma, ar kuru serveris pats piekrīt: „atbildes no manis var lasīt lapas no šīm izcelsmēm”.
Divas sekas pārsteidz cilvēkus:
- Pieprasījums bieži sasniedz serveri. CORS parasti bloķē tavam kodam atbildes lasīšanu, nevis serverim pieprasījuma saņemšanu. POST var būt saglabāts, pat ja redzēji kļūdu.
- To izpilda tikai pārlūki. curl, Postman un servera puses kods CORS ignorē pilnībā. Tāpēc „darbojas Postman” neko nepasaka par CORS.
1. solis: izlasi precīzo kļūdu
Atver izstrādātāju rīkus (ar peles labo pogu → Inspect), dodies uz Console un izlasi pilno ziņojumu. Chrome formulējums norāda, kāda problēma tev ir:
| Ziņojums satur | Kas nav kārtībā |
|---|---|
No 'Access-Control-Allow-Origin' header is present | Serveris nenosūtīja galveni vispār, vai pieprasījums neizdevās pirms nonākšanas līdz tavam CORS kodam (piemēram, 404 vai 500) |
The 'Access-Control-Allow-Origin' header has a value '...' that is not equal to the supplied origin | Serveris atļauj citu izcelsmi nekā tava |
Response to preflight request doesn't pass access control check | OPTIONS preflight neizdevās |
...must not be the wildcard '*' when the request's credentials mode is 'include' | Tu sūti sīkdatnes, un serveris atbildēja ar * |
Request header field authorization is not allowed | Serveris nav uzskaitījis šo galveni Access-Control-Allow-Headers |
Tad atver cilni Network, atrodi neizdevušos pieprasījumu (un jebkuru OPTIONS pieprasījumu pirms tā) un apskati tā statusa kodu un atbildes galvenes.
Vispirms pārbaudi statusa kodu. Daudzas „CORS kļūdas” patiesībā ir servera kļūda maskā. Ja serveris avarē vai atgriež 404, tā kļūdas atbilde bieži nesatur CORS galvenes, tāpēc pārlūks ziņo par CORS, nevis par īsto problēmu. Labo 500 vai 404, un CORS kļūda var pazust.
2. solis: izlem, vai no pārlūka vispār jāsauc šis API
Pirms pievienot galvenes, pajautā: vai pārlūkam vajadzētu sūtīt pieprasījumus tieši uz šo API?
- Trešās puses API, kam vajadzīga slepenā atslēga (OpenAI, Stripe slepenā atslēga, lielākā daļa e-pasta pakalpojumu) nekad nedrīkst izsaukt no pārlūka. Atslēga būtu redzama katram apmeklētājam. Izsauc to no sava backend, un CORS problēma pazūd, jo servera-uz-servera pieprasījumi uz CORS neattiecas. Skaties kā glabāt API atslēgas drošībā.
- Trešās puses API, ko tu nekontrolē un kas nesūta CORS galvenes, no tavas puses nevar salabot. Izsauc to no sava backend.
- Tavs pats API var tikt salabots, to pareizi konfigurējot. Turpini tālāk.
3. solis: labo serverī
Serverim jāpievieno pareizās galvenes visām atbildēm, arī kļūdu atbildēm.
Faktiskam pieprasījumam nosūti:
Access-Control-Allow-Origin: https://myapp.com(tava frontend precīzā izcelsme, bez slīpsvītras beigās)Vary: Origin, ja vērtība ir atkarīga no tā, kura izcelsme pieprasīja
Preflight OPTIONS pieprasījumam atbildi ar veiksmes statusu (200 vai 204) un:
Access-Control-Allow-Origin: https://myapp.comAccess-Control-Allow-Methods: GET, POST, PUT, PATCH, DELETEAccess-Control-Allow-Headers: Content-Type, Authorization(katra pielāgotā galvene, ko sūti)- Pēc izvēles
Access-Control-Max-Age: 600, lai pārlūks kādu laiku kešotu preflight
Lielākajā daļā ietvaru ir pakotne vai iestatījums, kas to dara. Express — pakotne cors; FastAPI — CORSMiddleware; ASP.NET Core — AddCors; Spring — @CrossOrigin vai CORS konfigurācija. Tipisks Express iestatījums:
import cors from "cors";
app.use(cors({
origin: ["https://myapp.com", "http://localhost:5173"],
credentials: true,
}));
Ieliec CORS apstrādi pirms savu maršrutu un autentifikācijas, lai preflight pieprasījumi (kuros nav pieteikšanās) netiktu noraidīti ar 401.
Ar AI veidotāju apraksti iestatījumu precīzi:
Frontend
https://myapp.comizsauc APIhttps://api.myapp.comun saņem „Response to preflight request doesn't pass access control check”. Konfigurē CORS API, lai atļautu tiešihttps://myapp.comun priekšskatījuma izcelsmi, atļauj GET, POST, PATCH, DELETE ar galvenēm Content-Type un Authorization, apstrādā OPTIONS pirms autentifikācijas un iekļauj CORS galvenes arī kļūdu atbildēs.
4. solis: apstrādā sīkdatnes un akreditācijas datus
Ja tavs frontend sūta sīkdatnes (piemēram, pieteikšanās sesiju) uz citu izcelsmi, abām pusēm jāsaskaņojas:
- Frontend
fetchiestatacredentials: "include", vai axioswithCredentials: true. - Serveris nosūta
Access-Control-Allow-Credentials: true. - Servera
Access-Control-Allow-Originjābūt precīzai izcelsmei, nevis*.
Starpvietņu sīkdatnēm arī vajag SameSite=None; Secure, un daži pārlūki ierobežo trešo pušu sīkdatnes vēl vairāk. Tas ir vēl viens iemesls dot priekšroku 5. solī aprakstītajai pieejai.
5. solis: izvairies no CORS ar vienas izcelsmes iestatījumu
Bieži tīrākais labojums ir nesūtīt starpizcelsmju pieprasījumus vispār. Pasniedz API no tās pašas izcelsmes, kur lapa, piemēram, https://myapp.com/api/...:
- Izstrādes vidē lielākā daļa izstrādes serveru var starpniekot. Vite opcija
server.proxyvar pārsūtīt/apiuz tavu backend citā portā, tāpēc pārlūks vienmēr runā tikai ar vienu izcelsmi. - Ražošanā maršrutē
/apiuz backend ar sava hostinga pārrakstīšanas vai starpnieka iestatījumiem, vai pasniedz frontend un API no viena servera.
Tad frontend sauc relatīvu ceļu, piemēram, fetch("/api/orders"). Nav starpizcelsmju pieprasījuma, nav starpizcelsmju preflight un nav sīkdatņu problēmu. Tas arī nozīmē, ka tu nekodē API domēnu, kas atšķiras starp priekšskatījumu un ražošanu.
Maini frontend, lai tas sauktu backend ar relatīviem /api ceļiem, nevis pilnu URL, un iestati izstrādes starpnieku, lai /api pārsūtītu uz API serveri. Pēc tam noņem CORS iestatījumus, kas vairs nav vajadzīgi.
Ko nedarīt
mode: "no-cors"fetch. Tas neko neapiet; tas dod tavam kodam tukšu, nelasāmu atbildi.- Pārlūka paplašinājumi, kas atslēdz CORS. Tie maina tikai tavu pārlūku. Katrs apmeklētājs joprojām redz kļūdu.
- Publiski „CORS starpnieka” pakalpojumi reāliem lietotnēm. Tie var lasīt un mainīt visu, kas tiem iet cauri, un tie reizēm nedarbojas.
Access-Control-Allow-Origin: *API, kas izmanto pieteikšanos. Tas tāpat nedarbojas ar akreditācijas datiem, un tas ir nepareizs noklusējums privātiem datiem.- Atgriezt jebkuru
Origingalveni atpakaļ, ļaujot akreditācijas datus. Tas ļauj jebkurai tīmekļa vietnei veikt pieprasījumus ar pieteikšanos tavu lietotāju vārdā. Izmanto atļauto sarakstu.
Biežākie cēloņi AI veidotās lietotnēs
| Situācija | Labojums |
|---|---|
| Frontend sauc trešās puses API ar slepenu atslēgu | Pārvieto izsaukumu uz backend |
| Darbojas priekšskatījumā, neizdodas publicētajā domēnā | Pievieno publicētās un pielāgotā domēna izcelsmes atļauto sarakstā vai izmanto relatīvus /api ceļus |
| Kļūda tikai uz POST, PUT vai DELETE | Preflight nav apstrādāts; pievieno OPTIONS apstrādi un atļautās galvenes |
| Kļūda parādījās pēc pieteikšanās pievienošanas | Akreditācijas datiem vajadzīga precīza izcelsme un Allow-Credentials |
| „CORS kļūda”, bet tīkla cilnē redzams 500 | Vispirms labo servera kļūdu |
API URL cieti ierakstīts uz localhost | Lieto relatīvus ceļus vai iestatījumu katrai videi |
CORS Mythex
Kad Mythex projektam ir gan vietne, gan API serveris, abi darbojas kā pakalpojumi vienā projektā, un starp tiem var pārslēgties priekšskatījumā. Ja aģentam lūdz, lai frontend sauc backend caur relatīvu /api ceļu, izstrādē starpniekotu, vairums CORS problēmu pazūd. Ja tomēr vajag starpizcelsmju izsaukumus, dod aģentam precīzo kļūdu no konsoles un iesaistītās izcelsmes. Pārbaudi rezultātu arī publicētajā lietotnē, jo tās adrese atšķiras no priekšskatījuma. Skaties Vairāku pakalpojumu lietotnes un API backend dokumentācijā, kā arī mūsu ceļvežus kā atkļūdot ar AI veidotu lietotni un frontend pret backend.
CORS kontrolsaraksts
- Izlasīta pilna konsoles kļūda un neizdevušos pieprasījuma statusa kods
- Izslēgta paslēpta 404 vai 500 kļūda
- API ar slepenām atslēgām tiek izsaukti no backend, nevis pārlūka
- Serveris nosūta
Access-Control-Allow-Originar precīzi atļautajām izcelsmēm - OPTIONS preflight atbildēts ar atļautajām metodēm un galvenēm, pirms autentifikācijas
- CORS galvenes ir arī kļūdu atbildēs
- Akreditācijas dati: precīza izcelsme,
Allow-Credentials: trueun pareizi sīkdatņu iestatījumi - Priekšskatījuma, publicētā un pielāgotā domēna izcelsmes aptvertas, vai izmantoti relatīvi
/apiceļi - Nav
no-cors, publisku starpnieku vai atgriešanas jebkuras izcelsmes saīsinājumu
Jautājumi
Ko nozīmē CORS kļūda?
Tava lapa, ielādēta no vienas izcelsmes, mēģināja nolasīt atbildi no citas izcelsmes, un tā servera atbildē nebija galveņu, kas to atļauj. Pārlūks bloķē tavam kodam atbildes nolasīšanu. Labojums ir serverī vai tajā, kā pieprasījums tiek maršrutēts, nevis frontend kodā.
Vai CORS kļūdu var novērst no frontend?
Ne pienācīgi. Iestatījumi, piemēram, mode: 'no-cors', tikai paslēpj atbildi no tava koda. To labo, liekot serverim nosūtīt pareizo galveni Access-Control-Allow-Origin, vai izsaucot API no sava backend vai vienas izcelsmes starpnieka.
Vai Access-Control-Allow-Origin: * ir drošs?
Tas ir labi publiskiem datiem, ko var lasīt ikviens, piemēram, publiskam API bez pieteikšanās. To nevar lietot ar sīkdatnēm vai citiem akreditācijas datiem, un privātiem API tev jāuzskaita precīzas atļautās izcelsmes.
Kāpēc pieprasījums darbojas Postman vai curl, bet ne pārlūkā?
CORS izpilda tikai pārlūki. Tādi rīki kā Postman un curl to nepiemēro, tāpēc pieprasījums tur var izdoties un tomēr tikt bloķēts, kad to veic lapas JavaScript.
Kas ir preflight pieprasījums?
Pieprasījumiem, kas nav vienkārši, piemēram, JSON POST vai pieprasījumam ar galveni Authorization, pārlūks vispirms nosūta OPTIONS pieprasījumu, jautājot serverim, kādas metodes un galvenes ir atļautas. Ja šis OPTIONS pieprasījums neizdodas vai nesatur pareizās galvenes, īstais pieprasījums nekad netiek nosūtīts.