XMLHttpRequest XXX'i yükleyemiyor 'Access-Control-Allow-Origin' başlığı yok


112

tl; dr; Aynı Menşe Politikası Hakkında

Bir express.js sunucusu örneğini başlatan bir Grunt sürecim var. Bu, Chrome'da (en son sürüm) geliştiricinin konsolundaki hata günlüğünde aşağıdakilerin göründüğü boş bir sayfa sunmaya başlayana kadar kesinlikle iyi çalışıyordu:

XMLHttpRequest https://www.example.com/ yükleyemiyor İstenen kaynakta 'Access-Control-Allow-Origin' başlığı yok. Bu nedenle ' http: // localhost: 4300 ' kaynağına erişime izin verilmiyor.

Sayfaya erişmemi engelleyen nedir?


Web sitesinde çalışıyorum ve beş dakika önce iyiydi.
Peter David Carter

1
CORS başlıklarını veriyor mu? belki bir kod
paylaşsaydınız

Makul bir şekilde. Hangi departmanı öğrenmek için sormalıyım? Çoğunlukla backbone.marionette işlerini yapıyorum ...
Peter David Carter

Evet. Sanırım departmanların organizasyonları zaten her zaman tek tip değil, bu yüzden muhtemelen belirsiz bir soru ama şirketimdeki arka uç / yönlendirme / sys-admin hakkında biraz bilgi sahibi olmak istiyorum ve bu alışmak için iyi bir bahane gibi görünüyordu Kendim, böylece gelecekte sorun çıkarsa yardımcı olabilirim.
Peter David Carter

Operasyonunuzun içinde sunucu tarafında birine sorardım. Daha önce erişebildiyseniz, sizin üzerinizde değiştirmiş olmalılar.
Larry Lane

Yanıtlar:


207

tl; dr - İlgili kısımları bulmayı kolaylaştırmak için sonunda bir özet ve cevapta başlıklar vardır. Her şeyi okumak, bunun neden farklı koşullarda nasıl geçerli olduğunu görmeyi kolaylaştırdığını anlamak için yararlı bir arka plan sağladığından tavsiye edilir .

Aynı Menşe Politikası Hakkında

Bu Aynı Menşe Politikasıdır . Tarayıcılar tarafından uygulanan bir güvenlik özelliğidir.

Özel durumunuz, XMLHttpRequest için nasıl uygulandığını gösteriyor (ve getirmeyi kullanırsanız aynı sonuçları alırsınız), ancak diğer şeyler için de geçerlidir (bir üzerine yüklenen görüntüler <canvas>veya bir'ye yüklenen belgeler gibi <iframe>), biraz farklı uygulamalar.

(Garip bir şekilde, CSS yazı tipleri için de geçerlidir, ancak bunun nedeni, bulunan dökümhanelerin DRM'de ısrar etmeleridir ve Aynı Köken Politikasının genellikle kapsadığı güvenlik sorunları için değil).

SÇP'ye duyulan ihtiyacı gösteren standart senaryo üç karakterle gösterilebilir :

  • Alice, web tarayıcısı olan bir kişidir
  • Bob bir web sitesi işletiyor ( https://www.[website].com/sizin örneğinizde)
  • Mallory bir web sitesi işletiyor ( http://localhost:4300sizin örneğinizde)

Alice, Bob'un sitesinde oturum açtı ve orada bazı gizli veriler var. Belki bir şirket intranetidir (yalnızca LAN'daki tarayıcılar tarafından erişilebilir) veya onun çevrimiçi bankacılığı (yalnızca bir kullanıcı adı ve şifre girdikten sonra aldığınız bir çerezle erişilebilir).

Alice, Alice'in tarayıcısının Bob'un web sitesine (çerezleri ile IP adresinden, vb.) HTTP isteğinde bulunmasına neden olan bazı JavaScript içeren Mallory'nin web sitesini ziyaret eder. Bu, .ppi'yi kullanmak XMLHttpRequestve okumak kadar basit olabilir responseText.

Tarayıcının Aynı Kaynak İlkesi, JavaScript'in Bob'un web sitesi tarafından döndürülen verileri okumasını engeller (Bob ve Alice, Mallory'nin erişmesini istemez). Eğer, örneğin, bir kullanan bir görüntü gösterebilmesi (Not <img>görüntünün içeriği) JavaScript (veya Mallory maruz kalmadığından dolayı size bu durumda karışımın içine tuval atmak sürece ... kökeni genelinde elemanı olacak bir aynı kökenli oluşturmak ihlal hatası).


Aynı Menşe Politikası, olması gerektiğini düşünmediğinizde neden geçerlidir?

Verilen herhangi bir URL için SÇP'ye ihtiyaç duyulmaması mümkündür. Durumun böyle olduğu birkaç yaygın senaryo şunlardır:

  • Alice, Bob ve Mallory aynı kişilerdir.
  • Bob tamamen halka açık bilgiler sağlıyor

… Ancak tarayıcının yukarıdakilerden herhangi birinin doğru olup olmadığını bilmesinin bir yolu yoktur, bu nedenle güven otomatik değildir ve SOP uygulanır. Tarayıcının verdiği veriyi farklı bir web sitesine vermesi için izin açıkça verilmelidir.


Aynı Kaynak Politikası neden yalnızca bir web sayfasındaki JavaScript için geçerlidir?

Tarayıcı uzantıları *, tarayıcı geliştirici araçlarındaki Ağ sekmesi ve Postman gibi uygulamalar yüklü yazılımlardır. Bir web sitesinden, farklı bir web sitesine ait olan JavaScript'e, yalnızca o farklı web sitesini ziyaret ettiğiniz için veri aktarmazlar . Yazılım yüklemek genellikle daha bilinçli bir seçim gerektirir.

Risk olarak kabul edilen üçüncü bir taraf (Mallory) yoktur.

*Çapraz kaynak sorunlarını önlemek için tarayıcı uzantılarının dikkatli bir şekilde yazılması gerekir. Örneğin Chrome belgelerine bakın .


Sayfadaki verileri JS ile okumadan neden görüntüleyebilirsiniz?

Mallory'nin sitesinin bir tarayıcının üçüncü bir şahıstan veri almasına ve görüntülemesine neden olabileceği birkaç durum vardır (örneğin, <img>bir görüntüyü görüntülemek için bir öğe ekleyerek ). Mallory'nin JavaScript'in bu kaynaktaki verileri okuması mümkün değildir, ancak yalnızca Alice'in tarayıcısı ve Bob'un sunucusu bunu yapabilir, bu nedenle hala güvenlidir.


CORS

Access-Control-Allow-OriginHTTP yanıtı başlığı hata mesajı parçasıdır belirtilen CORS Bob açıkça erişim Alice'in tarayıcı üzerinden veri Mallory'nin sitesine izin vermenize olanak sağlar standardı.

Temel bir uygulama şunları içerir:

Access-Control-Allow-Origin: *

… Herhangi bir web sitesinin verileri okumasına izin vermek için yanıt başlıklarında.

Access-Control-Allow-Origin: http://example.com/

… Yalnızca belirli bir sitenin ona erişmesine izin verir ve Bob, birden çok siteye erişmesine izin vermek için Origin istek başlığına dayalı olarak bunu dinamik olarak oluşturabilir .

Bob'un bu yanıt başlığını nasıl ayarladığına ilişkin ayrıntılar, Bob'un HTTP sunucusuna ve / veya sunucu tarafı programlama diline bağlıdır. Yardımcı olabilecek çeşitli genel yapılandırmalar için bir kılavuz koleksiyonu vardır .

CORS kurallarının uygulandığı model

NB: Bazı istekler karmaşıktır ve tarayıcının GET / POST / PUT / JS'nin yapmak istediği her isteği göndermeden önce sunucunun yanıt vermesi gereken bir ön kontrol SEÇENEKLERİ isteği gönderir. Yalnızca Access-Control-Allow-Originbelirli URL'lere eklenen CORS uygulamaları genellikle bununla tetiklenir.


Açıkçası, CORS aracılığıyla izin vermek, Bob'un yalnızca aşağıdaki durumlarda yapacağı bir şeydir:

  • Veriler özel değildi veya
  • Mallory güvenildi

Ama ben Bob değilim!

Mallory'nin bu başlığı eklemesi için standart bir mekanizma yoktur, çünkü Bob'un kendi kontrolünde olmadığı web sitesinden gelmesi gerekir.

Bob genel bir API çalıştırıyorsa, CORS'u açmak için bir mekanizma olabilir (belki de isteği belirli bir şekilde biçimlendirerek veya Bob'un sitesi için bir Geliştirici Portalı sitesinde oturum açtıktan sonra bir yapılandırma seçeneği). Bunun Bob tarafından uygulanan bir mekanizma olması gerekecek. Mallory, bir şeyin mevcut olup olmadığını görmek için Bob'un sitesindeki belgeleri okuyabilir veya Bob'la konuşup ondan CORS uygulamasını isteyebilir.


"Ön kontrol için yanıt" dan bahseden hata mesajları

Bazı çapraz kaynak talepleri önceden kontrol edilir .

Bu, (kabaca konuşursak) aşağıdakileri içeren çapraz kaynaklı bir talepte bulunmaya çalıştığınızda gerçekleşir:

  • Çerezler gibi kimlik bilgilerini içerir
  • Normal bir HTML formuyla oluşturulamaz (örneğin, bir formda kullanamayacağınız özel başlıklar veya bir İçerik Türü vardır enctype).

Ön kontrol gerektiren bir şeyi doğru yapıyorsanız

Bu durumlarda daha sonra cevabın kalan hala geçerlidir ama aynı zamanda sunucu olacak (uçuş öncesi isteği için dinleyebilir emin olmak gerekir OPTIONS(ve GET, POSTveya sağ ile kendisine gönderme çalışıyor) ve tepki edildi olursa olsun Access-Control-Allow-Originbaşlığı değil, aynı zamanda Access-Control-Allow-Methodsve Access-Control-Allow-Headersbelirli HTTP yöntemlerine veya başlıklarına izin vermek için.

Yanlışlıkla bir ön kontrolü tetikliyorsanız

Bazen insanlar Ajax isteklerini oluşturmaya çalışırken hatalar yapar ve bazen bunlar ön kontrol ihtiyacını tetikler. API, çapraz kaynaklı isteklere izin verecek şekilde tasarlanmışsa, ancak ön kontrol gerektiren herhangi bir şey gerektirmiyorsa, bu durumda erişimi kesebilir.

Bunu tetikleyen yaygın hatalar şunları içerir:

  • Access-Control-Allow-Originistek üzerine diğer CORS yanıt başlıklarını koymaya çalışıyor . Bunlar isteğe ait değildir, yardımcı hiçbir şey yapmayın (kendinize izin verebileceğiniz bir izin sisteminin amacı nedir?) Ve yalnızca yanıtta görünmelidir.
  • Content-Type: application/jsoniçeriğini açıklayacak bir istek gövdesi olmayan bir GET isteğine bir başlık koymaya çalışmak (genellikle yazarın kafasını karıştırdığında Content-Typeve Accept).

Her iki durumda da, fazladan istek başlığının kaldırılması genellikle bir ön kontrol ihtiyacını ortadan kaldırmak için yeterli olacaktır (bu, basit istekleri destekleyen ancak önceden kontrol edilmemiş istekleri desteklemeyen API'lerle iletişim kurarken sorunu çözecektir).


Opak tepkiler

Bazen bir HTTP isteğinde bulunmanız gerekir, ancak yanıtı okumanız gerekmez. örneğin, kayıt için sunucuya bir günlük mesajı gönderiyorsanız.

Eğer kullanıyorsanız API (yerine ), o zaman kullanım CORS çalışmayın için yapılandırabilirsiniz.fetchXMLHttpRequest

Bunun, CORS'un yapmasını istediğiniz herhangi bir şeyi yapmanıza izin vermeyeceğini unutmayın. Yanıtı okuyamayacaksınız. Ön kontrol gerektiren bir talepte bulunamayacaksınız.

Basit bir istekte bulunmanıza, yanıtı görmenize ve Developer Console'u hata mesajlarıyla doldurmanıza izin vermez.

Nasıl yapılacağı, kullanarak bir talepte bulunduğunuzda fetchve yanıtı CORS ile görüntüleme izni almadığınızda verilen Chrome hata mesajıyla açıklanmaktadır :

" Kaynak https://example.com/" konumunda getirme erişimi, https://example.netCORS politikası tarafından engellendi: Access-Control-Allow-Originİstenen kaynakta " " başlığı yok . Opak bir yanıt ihtiyaçlarınızı karşılıyorsa, CORS devre dışıyken kaynağı getirmek için isteğin modunu 'no-cors' olarak ayarlayın.

Böylece:

fetch("http://example.com", { mode: "no-cors" });

CORS Alternatifleri

JSONP

Bob ayrıca, JSONP gibi bir hack kullanarak verileri sağlayabilir; bu, CORS ortaya çıkmadan önce insanların çapraz kökenli Ajax'ı nasıl yaptıklarıdır.

Verileri, Mallory'nin sayfasına enjekte eden bir JavaScript programı biçiminde sunarak çalışır.

Bu, Mallory'nin Bob'a kötü amaçlı kod sağlamayacağına güvenmesini gerektirir.

Ortak temaya dikkat edin: Verileri sağlayan site, tarayıcıya üçüncü taraf bir sitenin tarayıcıya gönderdiği verilere erişmesinin uygun olduğunu bildirmelidir.

JSONP <script>, verileri sayfada zaten bulunan bir işlevi çağıran bir JavaScript programı biçiminde yüklemek için bir öğe ekleyerek çalıştığından, JSON döndüren bir URL'de JSONP tekniğini kullanmaya çalışmak başarısız olur - genellikle bir CORB hatasıyla - JSON JavaScript değil.

İki kaynağı tek bir kaynağa taşıyın

JS'nin çalıştığı HTML belgesi ve istenen URL aynı kaynakta ise (aynı şemayı, ana bilgisayar adını ve bağlantı noktasını paylaşıyorsa), aynı Kaynak İlkesi varsayılan olarak izin verir. CORS gerekli değildir.

Bir Proxy

Mallory olabilir (o sonra her zamanki gibi HTTP yoluyla Alice'in tarayıcısına onu sunucudan geçebileceği) veri getirmek için sunucu tarafı kodu kullanabilirsiniz.

Ya:

  • CORS başlıkları ekle
  • yanıtı JSONP'ye dönüştür
  • HTML belgesiyle aynı kaynaktan var

Bu sunucu tarafı kodu, üçüncü bir taraf (örneğin CORS Anywhere) tarafından yazılabilir ve barındırılabilir. Bunun gizlilikle ilgili sonuçlarına dikkat edin: Üçüncü taraf, sunucularında kimin neye proxy yaptığını izleyebilir.

Bob'un bunun olması için herhangi bir izin vermesi gerekmiyor.

Bu sadece Mallory ve Bob arasında olduğu için burada güvenlik etkileri yok. Bob'un, Mallory'nin Alice olduğunu düşünmesi ve Mallory'ye Alice ile Bob arasında gizli tutulması gereken verileri sağlamasının bir yolu yoktur.

Sonuç olarak, Mallory bu tekniği yalnızca halka açık verileri okumak için kullanabilir .

Bununla birlikte, başka birinin web sitesinden içerik almanın ve bunu kendi başınıza görüntülemenin telif hakkı ihlali olabileceğini ve sizi yasal işlemlere açabileceğini unutmayın.

Web uygulaması dışında bir şey yazmak

"Neden Aynı Kaynak İlkesi yalnızca bir web sayfasındaki JavaScript için geçerlidir" bölümünde belirtildiği gibi, bir web sayfasına JavaScript yazmayarak SOP'den kaçınabilirsiniz.

Bu, JavaScript ve HTML kullanmaya devam edemeyeceğiniz anlamına gelmez, ancak Node-WebKit veya PhoneGap gibi başka bir mekanizma kullanarak dağıtabileceğiniz anlamına gelir.

Tarayıcı uzantıları

Bir tarayıcı uzantısının, Aynı Kaynak Politikası uygulanmadan önce yanıtta CORS başlıklarını enjekte etmesi mümkündür.

Bunlar geliştirme için yararlı olabilir, ancak bir üretim sitesi için pratik değildir (sitenizdeki her kullanıcıdan, tarayıcılarının bir güvenlik özelliğini devre dışı bırakan bir tarayıcı uzantısı yüklemesini istemek mantıksızdır).

Ayrıca yalnızca basit isteklerle çalışma eğilimindedirler (ön kontrol SEÇENEKLERİ isteklerini ele alırken başarısız olurlar).

Yerel bir geliştirme sunucusuna sahip uygun bir geliştirme ortamına sahip olmak genellikle daha iyi bir yaklaşımdır.


Diğer güvenlik riskleri

SOP / CORS'un , bağımsız olarak ele alınması gereken XSS , CSRF veya SQL Injection saldırılarını azaltmadığını unutmayın .


Özet

  • Eğer yapabileceğiniz bir şey yoktur senin birileri için CORS erişimini sağlayacak istemci tarafı kodu başka sunucuya.
  • Sunucuyu kontrol ediyorsanız, istek şu şekilde yapılır: Ona CORS izinleri ekleyin.
  • Onu kontrol eden kişiyle arkadaşça davranıyorsanız: CORS izinleri eklemesini sağlayın.
  • Bir kamu hizmetiyse:
    • İstemci tarafı JavaScript ile erişim hakkında ne söylediklerini görmek için API belgelerini okuyun:
      • Size belirli URL'ler kullanmanızı söyleyebilirler
      • JSONP'yi destekleyebilirler
      • İstemci tarafı kodundan çapraz kaynaklı erişimi hiç desteklemeyebilirler (bu, özellikle her istekte kişiselleştirilmiş bir API Anahtarı iletmeniz gerekiyorsa, güvenlik gerekçesiyle kasıtlı bir karar olabilir).
    • İhtiyacınız olmayan bir ön kontrol talebini tetiklemediğinizden emin olun. API, basit istekler için izin verebilir ancak önceden kontrol edilmiş istekler için izin vermez.
  • Yukarıdakilerin hiçbiri geçerli değilse: konuşursan için tarayıcıya sahip olun sizin yerine sunucudan ve sonra sunucu diğer sunucudan veri almaya ve geçirir var. (Ayrıca, kullanabileceğiniz genel olarak erişilebilen kaynaklara CORS başlıklarını ekleyen üçüncü tarafça barındırılan hizmetler de vardır).

Yerel LAN'ı bir web sunucusu çalıştırırsam ve IP / URL'den ajax yüklemesi yapmaya çalışırsam bu işe yarayacak mı? Henüz denemedim. json verilerini
döndüren

@Ciastopiekarz - Normal aynı menşe / farklı menşe kuralları geçerlidir. Normal ağ yönlendirme kuralları geçerlidir.
Quentin

25
Sadece cors hakkında bir bağlantı yerine okuduğum en eksiksiz cevap ..
pungggi

@Quentin - Vay canına! +1! Alice CORS uzantısını kullanıyorsa ne anlamak olduğum Yani, sunucu onu http çağrıları olduğunu düşünüyor değil javascript ama normal bir aynı kökenli isteği gibi bir tarayıcı uzantısı ve davranır ondan?
snippetkid

@snippetkid - Hayır. Olağan durumda, sunucu her zaman yanıt olarak CORS başlıklarını gönderir ve isteğin nereden geldiğine dikkat etmez. Yanıttaki CORS başlıklarına dayalı olarak JS'ye verilere erişime izin vermek veya erişimi reddetmek tarayıcının sorumluluğundadır. (Ön kontrol talepleri söz konusu olduğunda, işler sunucuda biraz / biraz daha karmaşık hale gelir)
Quentin

3

Hedef sunucu, çapraz kaynak talebine izin vermelidir. Ekspres yoluyla buna izin vermek için, http seçenekleri isteğini işlemeniz yeterlidir:

app.options('/url...', function(req, res, next){
   res.header('Access-Control-Allow-Origin', "*");
   res.header('Access-Control-Allow-Methods', 'POST');
   res.header("Access-Control-Allow-Headers", "accept, content-type");
   res.header("Access-Control-Max-Age", "1728000");
   return res.sendStatus(200);
});

3

Kabul edilen cevapta bundan bahsedilmedi.

  • Bu tam soru için durum böyle değildir, ancak bu sorunu arayanlara yardımcı olabilir.
  • Bu, bazı durumlarda CORS hatalarını önlemek için istemci kodunuzda yapabileceğiniz bir şeydir .

Sen yararlanabilirler Basit İstekler .
Bir 'Basit İstekler'i gerçekleştirmek için, talebin birkaç koşulu karşılaması gerekir. Örneğin sadece izin POST, GETve HEADsıra sadece bazı verilmiş Başlıkları izin verilmesi gibi yöntem, (eğer tüm koşulları bulabilirsiniz burada ).

Müşteri kodu yaparsa açık kümesi Başlıkları etkilenmez (örneğin, "Kabul Et") isteğinde bir düzeltme değeri ile olabilir bazı müşteriler bazı "standart dışı" değerleri olarak bunu kabul etmek sunucuyu neden olan otomatik olarak bu Başlıkları kurarım olduğunu ortaya Basit İstek - size bir CORS hatası verecektir.


2

Bu, CORS hatası nedeniyle oluyor. CORS, Çapraz Kaynak Paylaşımı anlamına gelir. Basit bir deyişle, bu hata başka bir etki alanından bir etki alanına / kaynağa erişmeye çalıştığımızda ortaya çıkar.

Daha fazlasını buradan okuyun: jquery ile CORS hatası

Bunu düzeltmek için, diğer etki alanına erişiminiz varsa, sunucuda Access-Control-Allow-Origin'e izin vermeniz gerekir. Bu, başlıklara eklenebilir. Bunu tüm istekler / alanlar veya belirli bir alan için etkinleştirebilirsiniz.

Kaynaklar arası kaynak paylaşımı (CORS) gönderi isteği nasıl çalışır?

Bu bağlantılar yardımcı olabilir


0

Bu CORS sorunu daha fazla detaylandırılmadı (diğer nedenler için).

Bu sorunu şu anda farklı bir nedenle yaşıyorum. Ön ucum da 'Access-Control-Allow-Origin' başlık hatası veriyor.

Sadece yanlış URL'yi gösterdiğim için bu başlık düzgün şekilde yansıtılmadı (ki bunu yaptığını varsaymaya devam ettim). localhost (ön uç) -> güvenli olmayan http çağrısı (https olması gerekir), ön uçtaki API bitiş noktasının doğru protokole işaret ettiğinden emin olun.


0

Chrome konsolunda da aynı hatayı aldım.

Benim sorunum, http://yerine kullanarak siteye gitmeye çalışıyordum https://. Yani düzeltilecek bir şey yoktu, sadece kullanarak aynı siteye gitmek gerekiyordu https.


0

Bu hata bana 2 güne mal oldu. Sunucu günlüğümü kontrol ettim, tarayıcı Chrome / Edge ile Sunucu arasındaki Ön Kontrol Seçeneği isteği / yanıtı tamamdı. Ana neden, XHTMLRequest için GET / POST / PUT / DELETE sunucu yanıtının da aşağıdaki başlığa sahip olması gerektiğidir:

access-control-allow-origin: origin  

"kaynak" istek başlığındadır (Tarayıcı bunu sizin için istemek için ekleyecektir). Örneğin:

Origin: http://localhost:4221

Tümünü kabul etmek için aşağıdaki gibi yanıt başlığı ekleyebilirsiniz:

access-control-allow-origin: *  

veya aşağıdaki gibi belirli bir istek için yanıt başlığı:

access-control-allow-origin: http://localhost:4221 

Tarayıcılardaki mesajın anlaşılması açık değil: "... İstenen kaynak"

unutmayın: CORS localhost için iyi çalışıyor. farklı bağlantı noktası, farklı Etki Alanı anlamına gelir. hata mesajı alırsanız, sunucu tarafındaki CORS yapılandırmasını kontrol edin.


-1

Başlıklar eklenerek "Al" isteği "Seçenekler" isteğine dönüşür. Dolayısıyla, Cors politika sorunları ortaya çıkar. Sunucunuza "Seçenekler" talebini uygulamanız gerekir.


Sitemizi kullandığınızda şunları okuyup anladığınızı kabul etmiş olursunuz: Çerez Politikası ve Gizlilik Politikası.
Licensed under cc by-sa 3.0 with attribution required.