Bu cevap çok fazla zemini kapsıyor, bu yüzden üç bölüme ayrılıyor:
- "Erişim-Denetim-İzin Verme Başlığı Yok" sorunlarının çözümü için CORS proxy'si nasıl kullanılır
- CORS ön kontrolünden nasıl kaçınılır?
- “Access-Control-Allow-Origin üstbilgisi joker karakter olmamalıdır” sorunları nasıl düzeltilir
"Erişim-Denetim-İzin Verme Başlığı Yok" sorunlarının çözümü için CORS proxy'si nasıl kullanılır
Sunucunuzu kontrol edemiyorsanız, ön uç JavaScript kodunuz bir istek gönderir ve bu sunucudan gelen yanıtla ilgili sorun yalnızca gerekli Access-Control-Allow-Origin
başlığın olmamasıdır , yine de bir şeyler yaparak istekte bulunabilirsiniz. CORS vekili. Bunun nasıl çalıştığını göstermek için, önce CORS proxy'sini kullanmayan bazı kodlar aşağıdadır:
const url = "https://example.com"; // site that doesn’t send Access-Control-*
fetch(url)
.then(response => response.text())
.then(contents => console.log(contents))
.catch(() => console.log("Can’t access " + url + " response. Blocked by browser?"))
catch
Bloğun vurulmasının nedeni, tarayıcı bu kodun geri gelen yanıta erişmesini engeller https://example.com
. Ve tarayıcının bunu yapmasının nedeni, yanıtın Access-Control-Allow-Origin
yanıt başlığından yoksundur .
Şimdi, tam olarak aynı örnek, ancak yalnızca bir CORS proxy'si eklendi:
const proxyurl = "https://cors-anywhere.herokuapp.com/";
const url = "https://example.com"; // site that doesn’t send Access-Control-*
fetch(proxyurl + url) // https://cors-anywhere.herokuapp.com/https://example.com
.then(response => response.text())
.then(contents => console.log(contents))
.catch(() => console.log("Can’t access " + url + " response. Blocked by browser?"))
Not: https://cors-anywhere.herokuapp.com denediğinizde kullanılamıyor veya kullanılamıyorsa, Heroku'da kendi CORS Anywhere sunucunuzu sadece 2-3 dakikada nasıl dağıtacağınız için aşağıya bakın.
Yukarıdaki ikinci kod snippet'i, istek URL'sini alıp https://cors-anywhere.herokuapp.com/https://example.com ( yalnızca proxy URL'sinin önüne ekleyerek) olarak değiştirerek yanıta başarıyla erişebilir . o proxy üzerinden yapılma talebi, daha sonra:
- İsteği adresine yönlendirir
https://example.com
.
- Adlı kullanıcıdan yanıt alır
https://example.com
.
Access-Control-Allow-Origin
Yanıtı yanıta ekler .
- Bu yanıtı, eklenen üstbilgiyle, istekte bulunan ön uç koduna geri gönderir.
Daha sonra tarayıcı, ön uç kodunun yanıta erişmesine izin verir, çünkü Access-Control-Allow-Origin
yanıt üstbilgisiyle bu yanıt tarayıcının gördüğü şeydir.
Https://github.com/Rob--W/cors-anywhere/ adresindeki kodu kullanarak kendi proxy'nizi kolayca çalıştırabilirsiniz .
5 komutla kelimenin tam anlamıyla 2-3 dakikada kendi proxy'nizi kolayca Heroku'ya dağıtabilirsiniz:
git clone https://github.com/Rob--W/cors-anywhere.git
cd cors-anywhere/
npm install
heroku create
git push heroku master
Bu komutları çalıştırdıktan sonra, kendi https://cryptic-headland-94862.herokuapp.com/ adresinde çalışan kendi CORS Anywhere sunucunuz olur . Bu durumda, istek URL'nize önek eklemek https://cors-anywhere.herokuapp.com
yerine, kendi örneğinizin URL'sine önek koyun; örneğin, https://cryptic-headland-94862.herokuapp.com/https://example.com .
Bu nedenle, https: //cors-anywhere.herokuapp.com'u kullanmaya çalıştığınızda, aşağı olduğunu (bazen bazen olur) bulursanız, bir Heroku hesabı almayı (zaten yapmadıysanız) düşünün ve 2 veya Heroku üzerinde kendi CORS Anywhere sunucunuzu dağıtmak için yukarıdaki adımları uygulamanız gerekir.
İster kendi kendinize çalıştırın, ister https://cors-anywhere.herokuapp.com veya başka bir açık proxy kullanın, bu çözüm, istek tarayıcıları bir CORS ön kontrol OPTIONS
isteği yapmaya yönlendiren bir istek olsa bile çalışır; çünkü bu durumda, proxy ayrıca ön kontrolün başarılı olması için gereken Access-Control-Allow-Headers
ve Access-Control-Allow-Methods
başlıklarını da geri gönderir .
CORS ön kontrolünden nasıl kaçınılır?
Sorudaki kod, bir Authorization
başlık gönderdiğinden CORS ön kontrolünü tetikler .
https://developer.mozilla.org/en-US/docs/Web/HTTP/Access_control_CORS#Preflighted_requests
Bu olmasa bile, Content-Type: application/json
başlık ön kontrolünü de tetikleyecektir.
“Ön kontrol” ne anlama gelir: tarayıcı POST
söz konusu kodda denemeden önce, OPTIONS
sunucuya bir istek gönderir - sunucunun ve başlıklarını POST
içeren bir çapraz menşe almayı Authorization
seçip Content-Type: application/json
seçmediğini belirlemek için.
Küçük bir kıvrılma komut dosyası ile oldukça iyi çalışıyor - verilerimi aldım.
Doğru bir şekilde test curl
etmek için OPTIONS
, tarayıcının gönderdiği ön kontrol isteğini taklit etmelisiniz :
curl -i -X OPTIONS -H "Origin: http://127.0.0.1:3000" \
-H 'Access-Control-Request-Method: POST' \
-H 'Access-Control-Request-Headers: Content-Type, Authorization' \
"https://the.sign_in.url"
… https://the.sign_in.url
Yerine gerçek sign_in
URL'niz ne olursa olsun .
Tarayıcının bu OPTIONS
istekte görmesi gereken yanıt şu başlıkları içermelidir:
Access-Control-Allow-Origin: http://127.0.0.1:3000
Access-Control-Allow-Methods: POST
Access-Control-Allow-Headers: Content-Type, Authorization
Eğer OPTIONS
yanıt bu başlıkları içermez, tarayıcı hemen orada duracak ve hatta gönderme girişiminde asla POST
isteği. Ayrıca, yanıtın HTTP durum kodu 2xx (genellikle 200 veya 204) olmalıdır. Başka bir durum kodu varsa, tarayıcı burada durur.
Söz konusu sunucu, OPTIONS
isteğe 501 durum koduyla yanıt veriyor. Bu, görünüşe göre OPTIONS
isteklere destek uygulamadığını belirtmeye çalıştığı anlamına geliyor . Diğer sunucular genellikle bu durumda 405 "Yönteme izin verilmiyor" durum kodu ile yanıt verir.
Dolayısıyla POST
, sunucu bu OPTIONS
isteğe 405 veya 501 veya 200 veya 204 dışında bir şeyle yanıt verirse veya gerekli olanlara yanıt vermezse , ön uç JavaScript kodunuzdan doğrudan bu sunucuya istekte bulunamazsınız. yanıt başlıkları.
Söz konusu vaka için ön kontrol tetiklemekten kaçınmanın yolu:
- sunucu bir
Authorization
istek üstbilgisi gerektirmediyse ancak bunun yerine (örneğin) POST
isteğin gövdesine katıştırılmış kimlik doğrulama verilerine veya bir sorgu parametresi olarak kullanıldıysa
- sunucu
POST
gövdenin bir Content-Type: application/json
medya türüne sahip olmasını gerektirmediyse, bunun yerine POST
gövdeyi değeri JSON verisi olan (veya her neyse) application/x-www-form-urlencoded
adlı bir parametre ile kabul json
ettiğinde
“Access-Control-Allow-Origin üstbilgisi joker karakter olmamalıdır” sorunları nasıl düzeltilir
Başka bir hata mesajı alıyorum:
Yanıttaki 'Access-Control-Allow-Origin' üstbilgisinin değeri, isteğin kimlik bilgileri modu 'dahil' olduğunda '*' joker karakteri olmamalıdır. Bu nedenle ' http://127.0.0.1:3000 ' kaynağına erişim izni verilmiyor. XMLHttpRequest tarafından başlatılan isteklerin kimlik bilgileri modu withCredentials özniteliği tarafından denetlenir.
Kimlik bilgileri içeren bir istek için tarayıcılar, Access-Control-Allow-Origin
yanıt üstbilgisinin değeri ise ön uç JavaScript kodunuzun yanıta erişmesine izin vermez *
. Bunun yerine, bu durumda değer, ön uç kodunuzun kökeni ile tam olarak eşleşmelidir http://127.0.0.1:3000
.
MDN HTTP erişim denetimi (CORS) makalesinde Kimlik doğrulamalı istekler ve joker karakterler konusuna bakın.
İsteği gönderdiğiniz sunucuyu kontrol ederseniz, bu durumla başa çıkmanın yaygın bir yolu, sunucuyu Origin
istek üstbilgisinin değerini alacak şekilde yapılandırmak ve bunu Access-Control-Allow-Origin
yanıt üstbilgisinin değerine yansıtır / yansıtmaktır . Örneğin, nginx ile:
add_header Access-Control-Allow-Origin $http_origin
Ama bu sadece bir örnek; diğer (web) sunucu sistemleri, yankı değerlerini yansıtmak için benzer yollar sağlar.
Chrome kullanıyorum. Ayrıca bu Chrome CORS Eklentisini kullanmayı denedim
Görünüşe göre Chrome CORS eklentisi Access-Control-Allow-Origin: *
, tarayıcının gördüğü yanıta basitçe basitçe bir başlık ekliyor . Eklenti daha akıllı olsaydı, yapacağı şey o sahte Access-Control-Allow-Origin
yanıt başlığının değerini ön uç JavaScript kodunuzun gerçek kaynağına ayarlamaktır http://127.0.0.1:3000
.
Bu yüzden test için bile bu eklentiyi kullanmaktan kaçının. Bu sadece dikkat dağıtıcı. Sunucudan gelen yanıtları tarayıcı filtrelemeden test etmek istiyorsanız curl -H
, yukarıdaki gibi kullanmanız daha iyi olur .
Sorudaki istek için ön uç JavaScript kodu fetch(…)
:
headers.append('Access-Control-Allow-Origin', 'http://localhost:3000');
headers.append('Access-Control-Allow-Credentials', 'true');
Bu çizgileri kaldırın. Access-Control-Allow-*
Başlık olduğu tepki başlıkları. Onları hiçbir zaman bir istekte göndermek istemezsiniz. Sahip olacağınız tek etki, bir tarayıcıyı ön kontrol yapmak için tetiklemektir.