Cara Betulkan Ralat CORS (dan Sebab Ia Berlaku)
Ralat CORS bermaksud halaman web anda cuba membaca respons dari asal yang berbeza (domain, port atau protokol lain), dan pelayan itu tidak menghantar header yang menyatakan ia dibenarkan. Pelayar menyekat respons untuk melindungi pengguna. Anda membetulkannya di pelayan, dengan mengembalikan header Access-Control-Allow-Origin untuk asal laman anda dan mengendalikan permintaan preflight OPTIONS, atau anda mengelaknya dengan menghantar permintaan melalui bahagian belakang anda sendiri pada asal yang sama.
Ia antara ralat yang paling mengelirukan dalam pembangunan web kerana permintaan selalunya sampai ke pelayan dengan baik. Panduan ini menerangkan apa yang berlaku dan cara membetulkan setiap varian.
Apa maksud "asal"
Asal ialah gabungan protokol, domain dan port:
| URL | Asal |
|---|---|
https://myapp.com/dashboard | https://myapp.com |
https://api.myapp.com/users | https://api.myapp.com (subdomain berbeza, jadi asal berbeza) |
http://localhost:5173 | http://localhost:5173 |
http://localhost:3000 | http://localhost:3000 (port berbeza, jadi asal berbeza) |
Pelayar mengikut dasar asal yang sama: JavaScript pada halaman bebas membaca respons dari asalnya sendiri, tetapi tidak dari asal lain. CORS (Cross-Origin Resource Sharing) ialah sistem yang membolehkan pelayan membuat pilihan: “respons daripada saya boleh dibaca oleh halaman dari asal ini.”
Dua akibat yang mengejutkan ramai orang:
- Permintaan selalunya sampai ke pelayan. CORS biasanya menghalang kod anda daripada membaca respons, bukan menghalang pelayan daripada menerima permintaan. Satu POST mungkin telah disimpan walaupun anda nampak ralat.
- Hanya pelayar yang menguatkuasakannya. curl, Postman dan kod bahagian pelayan mengabaikan CORS sepenuhnya. Sebab itu “ia berfungsi dalam Postman” tidak memberitahu anda apa-apa tentang CORS.
Langkah 1: Baca ralat tepat
Buka alat pembangun (klik kanan → Inspect), pergi ke Console, dan baca mesej penuh. Perkataan Chrome menunjukkan jenis masalah anda:
| Mesej mengandungi | Apa yang salah |
|---|---|
No 'Access-Control-Allow-Origin' header is present | Pelayan tidak menghantar header langsung, atau permintaan gagal sebelum mencapai kod CORS anda (contohnya 404 atau 500) |
The 'Access-Control-Allow-Origin' header has a value '...' that is not equal to the supplied origin | Pelayan membenarkan asal yang berbeza daripada anda |
Response to preflight request doesn't pass access control check | Preflight OPTIONS gagal |
...must not be the wildcard '*' when the request's credentials mode is 'include' | Anda menghantar kuki, dan pelayan membalas dengan * |
Request header field authorization is not allowed | Pelayan tidak menyenaraikan header itu dalam Access-Control-Allow-Headers |
Kemudian buka tab Network, cari permintaan yang gagal (dan sebarang permintaan OPTIONS sebelumnya), dan lihat kod status serta header respons.
Semak kod status dahulu. Banyak “ralat CORS” sebenarnya ralat pelayan yang menyamar. Jika pelayan ranap atau mengembalikan 404, respons ralatnya selalunya tidak mempunyai header CORS, jadi pelayar melaporkan CORS dan bukannya masalah sebenar. Betulkan 500 atau 404, dan ralat CORS mungkin hilang.
Langkah 2: Tentukan sama ada anda perlu memanggil API itu dari pelayar
Sebelum menambah header, tanya: adakah pelayar patut memanggil API ini secara langsung?
- API pihak ketiga yang memerlukan kunci rahsia (OpenAI, kunci rahsia Stripe, kebanyakan perkhidmatan e-mel) tidak sepatutnya dipanggil dari pelayar. Kunci itu akan kelihatan kepada setiap pelawat. Panggil dari bahagian belakang anda, dan masalah CORS hilang, kerana permintaan pelayan-ke-pelayan tidak tertakluk kepada CORS. Lihat cara memastikan kunci API selamat.
- API pihak ketiga yang anda tidak kawal dan tidak menghantar header CORS tidak boleh dibetulkan dari pihak anda. Panggil dari bahagian belakang anda.
- API anda sendiri boleh dibetulkan dengan mengkonfigurasikannya dengan betul. Teruskan di bawah.
Langkah 3: Betulkan pada pelayan anda
Pelayan mesti menambah header yang betul pada setiap respons, termasuk respons ralat.
Untuk permintaan sebenar, hantar:
Access-Control-Allow-Origin: https://myapp.com(asal tepat bahagian hadapan anda, tanpa garis miring akhir)Vary: Origin, jika nilainya bergantung pada asal yang meminta
Untuk permintaan preflight OPTIONS, balas dengan status berjaya (200 atau 204) dan:
Access-Control-Allow-Origin: https://myapp.comAccess-Control-Allow-Methods: GET, POST, PUT, PATCH, DELETEAccess-Control-Allow-Headers: Content-Type, Authorization(setiap header tersuai yang anda hantar)- Pilihan
Access-Control-Max-Age: 600, supaya pelayar menyimpan preflight dalam cache untuk seketika
Kebanyakan rangka kerja mempunyai pakej atau tetapan yang melakukan ini. Dalam Express, pakej cors; dalam FastAPI, CORSMiddleware; dalam ASP.NET Core, AddCors; dalam Spring, @CrossOrigin atau konfigurasi CORS. Persediaan Express yang tipikal:
import cors from "cors";
app.use(cors({
origin: ["https://myapp.com", "http://localhost:5173"],
credentials: true,
}));
Letakkan pengendalian CORS sebelum laluan dan pengesahan anda, supaya permintaan preflight (yang tidak membawa log masuk) tidak ditolak dengan 401.
Dengan pembina AI, terangkan persediaan dengan tepat:
Bahagian hadapan di
https://myapp.commemanggil API dihttps://api.myapp.comdan mendapat "Response to preflight request doesn't pass access control check". Konfigurasikan CORS pada API untuk membenarkan tepathttps://myapp.comdan asal pratonton, benarkan GET, POST, PATCH, DELETE dengan header Content-Type dan Authorization, kendalikan OPTIONS sebelum pengesahan, dan sertakan header CORS pada respons ralat juga.
Langkah 4: Kendalikan kuki dan kredensial
Jika bahagian hadapan anda menghantar kuki (contohnya sesi log masuk) ke asal lain, kedua-dua belah mesti bersetuju:
- Bahagian hadapan menetapkan
credentials: "include"padafetch, atauwithCredentials: truepada axios. - Pelayan menghantar
Access-Control-Allow-Credentials: true. Access-Control-Allow-Originpelayan mesti asal yang tepat, bukan*.
Kuki merentas tapak juga memerlukan SameSite=None; Secure pada kuki, dan sesetengah pelayar menyekat kuki pihak ketiga dengan lebih ketat. Itu satu lagi sebab untuk mengutamakan pendekatan dalam Langkah 5.
Langkah 5: Elakkan CORS dengan persediaan asal yang sama
Selalunya pembetulan yang paling kemas ialah tidak membuat permintaan merentas asal sama sekali. Hidangkan API dari asal yang sama dengan halaman, contohnya di https://myapp.com/api/...:
- Dalam pembangunan, kebanyakan pelayan pembangunan boleh memproksi. Pilihan
server.proxyVite boleh memajukan/apike bahagian belakang anda pada port lain, supaya pelayar hanya bercakap dengan satu asal. - Dalam pengeluaran, lalukan
/apike bahagian belakang melalui tetapan rewrite atau proksi hos anda, atau hidangkan bahagian hadapan dan API dari satu pelayan.
Bahagian hadapan kemudian memanggil laluan relatif seperti fetch("/api/orders"). Tiada permintaan merentas asal, tiada preflight merentas asal, dan tiada masalah kuki. Ia juga bermakna anda tidak mengkod keras domain API yang berbeza antara pratonton dan pengeluaran.
Tukar bahagian hadapan untuk memanggil bahagian belakang dengan laluan /api relatif dan bukannya URL penuh, dan tetapkan proksi pembangunan supaya /api dimajukan ke pelayan API. Kemudian buang sebarang tetapan CORS yang tidak diperlukan lagi.
Apa yang tidak perlu dilakukan
mode: "no-cors"dalamfetch. Ia tidak memintas apa-apa; ia memberi kod anda respons kosong yang tidak boleh dibaca.- Sambungan pelayar yang melumpuhkan CORS. Ia hanya menukar pelayar anda. Setiap pelawat masih melihat ralat itu.
- Perkhidmatan “proksi CORS” awam untuk aplikasi sebenar. Mereka boleh membaca dan menukar semua yang melaluinya, dan ia sering tumbang.
Access-Control-Allow-Origin: *pada API yang menggunakan log masuk. Ia tidak berfungsi dengan kredensial juga, dan ia lalai yang salah untuk data persendirian.- Memantulkan sebarang header
Originkembali dengan kredensial dibenarkan. Itu membolehkan mana-mana laman web membuat permintaan log masuk bagi pihak pengguna anda. Gunakan senarai yang dibenarkan.
Punca biasa dalam aplikasi yang dibina AI
| Situasi | Pembetulan |
|---|---|
| Bahagian hadapan memanggil API pihak ketiga dengan kunci rahsia | Pindahkan panggilan ke bahagian belakang |
| Berfungsi dalam pratonton, gagal pada domain yang diterbitkan | Tambah asal yang diterbitkan dan domain tersuai ke senarai yang dibenarkan, atau gunakan laluan /api relatif |
| Ralat hanya pada POST, PUT atau DELETE | Preflight tidak dikendalikan; tambah pengendalian OPTIONS dan header yang dibenarkan |
| Ralat muncul selepas menambah log masuk | Kredensial memerlukan asal yang tepat dan Allow-Credentials |
| “Ralat CORS” tetapi tab Network menunjukkan 500 | Betulkan ralat pelayan dahulu |
URL API dikod keras kepada localhost | Gunakan laluan relatif atau tetapan khusus persekitaran |
CORS dalam Mythex
Apabila projek Mythex mempunyai laman web dan pelayan API, kedua-duanya berjalan sebagai perkhidmatan dalam projek yang sama, dan anda boleh bertukar antara mereka dalam pratonton. Meminta ejen supaya bahagian hadapan memanggil bahagian belakang melalui laluan /api relatif, diproksikan dalam pembangunan, mengelakkan kebanyakan masalah CORS. Jika anda memang memerlukan panggilan merentas asal, berikan ejen ralat tepat dari konsol dan asal yang terlibat. Semak hasilnya pada aplikasi yang diterbitkan juga, kerana alamatnya berbeza daripada pratonton. Lihat Aplikasi berbilang perkhidmatan dan Bahagian belakang API dalam dokumentasi, dan panduan kami tentang menyahpepijat aplikasi yang dibina AI dan bahagian hadapan berbanding bahagian belakang.
Senarai semak CORS
- Baca ralat konsol penuh dan kod status permintaan yang gagal
- Menolak 404 atau 500 yang tersembunyi
- API yang menggunakan kunci rahsia dipanggil dari bahagian belakang, bukan pelayar
- Pelayan menghantar
Access-Control-Allow-Origindengan asal yang tepat dibenarkan - Preflight
OPTIONSdijawab dengan kaedah dan header yang dibenarkan, sebelum pengesahan - Header CORS hadir pada respons ralat
- Kredensial: asal yang tepat,
Allow-Credentials: true, dan tetapan kuki yang betul - Asal pratonton, diterbitkan dan domain tersuai semuanya diliputi, atau laluan
/apirelatif digunakan - Tiada
no-cors, proksi awam, atau pintasan memantulkan sebarang asal
Soalan lazim
Apa maksud ralat CORS?
Halaman anda, yang dimuatkan dari satu asal, cuba membaca respons dari asal yang berbeza, dan pelayan itu tidak menyertakan header yang membenarkannya. Pelayar menyekat kod anda daripada membaca respons. Pembetulannya ada di pelayan, atau dalam cara permintaan dilalukan, bukan dalam kod bahagian hadapan.
Bolehkah saya membetulkan ralat CORS dari bahagian hadapan?
Tidak dengan betul. Tetapan seperti mode: 'no-cors' hanya menyembunyikan respons daripada kod anda. Anda membetulkannya dengan membuat pelayan menghantar header Access-Control-Allow-Origin yang betul, atau dengan memanggil API dari bahagian belakang anda sendiri atau proksi asal yang sama.
Adakah Access-Control-Allow-Origin: * selamat?
Ia sesuai untuk data awam yang sesiapa pun boleh baca, seperti API awam tanpa log masuk. Ia tidak boleh digunakan dengan kuki atau kredensial lain, dan untuk API persendirian anda sepatutnya menyenaraikan asal yang tepat yang dibenarkan.
Kenapa permintaan saya berfungsi dalam Postman atau curl tetapi tidak dalam pelayar?
CORS hanya dikuatkuasakan oleh pelayar. Alat seperti Postman dan curl tidak menggunakannya, jadi permintaan boleh berjaya di sana dan masih disekat apabila JavaScript halaman membuat permintaan itu.
Apa itu permintaan preflight?
Untuk permintaan yang tidak mudah, seperti POST JSON atau yang mempunyai header Authorization, pelayar mula-mula menghantar permintaan OPTIONS untuk bertanya pelayan kaedah dan header mana yang dibenarkan. Jika permintaan OPTIONS itu gagal atau tidak mempunyai header yang betul, permintaan sebenar tidak pernah dihantar.