XMLHttpRequest nie może załadować XXX Nie nagłówka „Access-Control-Allow-Origin”

112

tl; dr; O tej samej polityce pochodzenia

Mam proces Grunt, który inicjuje wystąpienie serwera express.js. Do tej pory działało to absolutnie dobrze, kiedy zaczęło wyświetlać pustą stronę, a w dzienniku błędów w konsoli programisty w Chrome (najnowsza wersja) pojawiały się następujące informacje:

XMLHttpRequest nie może załadować https://www.example.com/ Żądanego zasobu nie ma nagłówka „Access-Control-Allow-Origin”. Dlatego źródło „ http: // localhost: 4300 ” nie ma dostępu.

Co powstrzymuje mnie przed dostępem do strony?

Peter David Carter
źródło
Pracuję nad stroną internetową i pięć minut temu było dobrze.
Peter David Carter
1
czy generuje nagłówki CORS? być może gdybyś udostępnił jakiś kod, byłoby to łatwiejsze do zobaczenia
Jaromanda X
Prawdopodobnie. Który dział powinienem zapytać, żeby się dowiedzieć? Zajmuję się głównie
Peter David Carter,
Tak. Przypuszczam, że organizacje działów i tak nie zawsze są jednolite, więc jest to prawdopodobnie mgliste pytanie, ale chciałbym dowiedzieć się trochę o sprawach dotyczących zaplecza / routingu / sys-admin w mojej firmie i wydawało się, że to dobry pretekst do zapoznania się siebie, więc jeśli w przyszłości pojawią się problemy, mogę pomóc.
Peter David Carter
Chciałbym poprosić kogoś po stronie serwera w twojej operacji. Musieli go zmienić na tobie, jeśli wcześniej miałeś do niego dostęp.
Larry Lane

Odpowiedzi:

206

tl; dr - na końcu znajduje się podsumowanie i nagłówki odpowiedzi, aby ułatwić znalezienie odpowiednich części. Zaleca się jednak przeczytanie wszystkiego, ponieważ zapewnia przydatne tło do zrozumienia, dlaczego , dzięki czemu łatwiej jest zobaczyć, jak można zastosować w różnych okolicznościach.

O tej samej polityce pochodzenia

To jest ta sama polityka pochodzenia . Jest to funkcja bezpieczeństwa wdrażana przez przeglądarki.

Twój konkretny przypadek pokazuje, jak jest zaimplementowany dla XMLHttpRequest (i uzyskasz identyczne wyniki, jeśli użyjesz funkcji pobierania), ale dotyczy to również innych rzeczy (takich jak obrazy załadowane do <canvas>lub dokumenty załadowane do pliku <iframe>), po prostu z nieco inne implementacje.

(Co dziwne, dotyczy to również czcionek CSS, ale to dlatego, że znalezione odlewnie nalegały na DRM, a nie w kwestiach bezpieczeństwa, które zwykle obejmuje ta sama polityka pochodzenia).

Standardowy scenariusz, który pokazuje potrzebę SOP, można przedstawić trzema znakami :

  • Alicja to osoba z przeglądarką internetową
  • Bob prowadzi witrynę internetową ( https://www.[website].com/w Twoim przykładzie)
  • Mallory prowadzi witrynę internetową ( http://localhost:4300w Twoim przykładzie)

Alicja jest zalogowana na stronie Boba i ma tam pewne poufne dane. Być może jest to firmowy intranet (dostępny tylko dla przeglądarek w sieci LAN) lub jej bankowość internetowa (dostępna tylko za pomocą pliku cookie, który otrzymujesz po wprowadzeniu nazwy użytkownika i hasła).

Alicja odwiedza witrynę Mallory, która zawiera JavaScript, który powoduje, że przeglądarka Alicji wysyła żądanie HTTP do witryny Boba (z jej adresu IP z plikami cookie itp.). Może to być tak proste, jak używanie XMLHttpRequesti czytanie responseText.

Polityka tego samego źródła przeglądarki zapobiega odczytywaniu przez JavaScript danych zwróconych przez witrynę internetową Boba (do której Bob i Alicja nie chcą, aby Mallory miał dostęp). (Należy pamiętać, że można na przykład wyświetlać obraz za pomocą <img>elementu całej pochodzeniu, ponieważ zawartość obrazu nie jest narażona na JavaScript (lub Mallory) ... chyba że rzucisz płótno do mieszanki w takim przypadku będzie generują tego samego pochodzenia błąd naruszenia).


Dlaczego zasady dotyczące tego samego pochodzenia mają zastosowanie, jeśli uważasz, że nie powinny

Dla dowolnego adresu URL możliwe jest, że SOP nie jest potrzebny. Oto kilka typowych scenariuszy, w których ma to miejsce:

  • Alice, Bob i Mallory to ta sama osoba.
  • Bob podaje całkowicie publiczne informacje

… Ale przeglądarka nie ma możliwości dowiedzenia się, czy którekolwiek z powyższych jest prawdą, więc zaufanie nie jest automatyczne i stosowana jest SOP. Zezwolenie musi być wyraźnie udzielone, zanim przeglądarka przekaże dane, które otrzymała, do innej witryny internetowej.


Dlaczego ta sama polityka pochodzenia dotyczy tylko kodu JavaScript na stronie internetowej

Rozszerzenia przeglądarki *, karta Sieć w narzędziach programistycznych przeglądarki i aplikacje, takie jak Postman, są instalowane jako oprogramowanie. Nie przekazują danych z jednej witryny do kodu JavaScript należącego do innej witryny tylko dlatego, że odwiedziłeś tę inną witrynę . Instalowanie oprogramowania zwykle wymaga bardziej świadomego wyboru.

Nie ma osoby trzeciej (Mallory), która jest uważana za ryzyko.

*Rozszerzenia przeglądarki muszą być napisane ostrożnie, aby uniknąć problemów z różnymi źródłami. Zobacz na przykład dokumentację Chrome .


Dlaczego możesz wyświetlać dane na stronie bez czytania ich za pomocą JS

Istnieje szereg okoliczności, w których witryna Mallory może spowodować, że przeglądarka pobierze dane od strony trzeciej i wyświetli je (np. Poprzez dodanie <img>elementu wyświetlającego obraz). Jednak JavaScript Mallory'ego nie może odczytać danych z tego zasobu, tylko przeglądarka Alicji i serwer Boba mogą to zrobić, więc jest to nadal bezpieczne.


CORS

Access-Control-Allow-OriginHTTP odpowiedzi Nagłówek, o którym mowa w komunikacie o błędzie jest częścią CORS standardowych co pozwala Bob jawnie zezwolić na miejscu Mallory'ego aby uzyskać dostęp do danych za pośrednictwem przeglądarki Alicji.

Podstawowa implementacja obejmowałaby po prostu:

Access-Control-Allow-Origin: *

… W nagłówkach odpowiedzi, aby umożliwić dowolnej witrynie internetowej odczyt danych.

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

… Pozwoliłoby na dostęp do niego tylko określonej witrynie, a Bob może dynamicznie wygenerować go na podstawie nagłówka Origin żądania, aby umożliwić dostęp do niego wielu witrynom, ale nie wszystkim.

Szczegóły, w jaki sposób Bob ustawia ten nagłówek odpowiedzi, zależą od serwera HTTP Roberta i / lub języka programowania po stronie serwera. Istnieje zbiór przewodników dotyczących różnych typowych konfiguracji, które mogą być pomocne.

Model zastosowania reguł CORS

NB: Niektóre żądania są złożone i wysyłają żądanie OPCJI inspekcji wstępnej , na które serwer będzie musiał odpowiedzieć, zanim przeglądarka wyśle ​​GET / POST / PUT / Cokolwiek żąda JS. Implementacje CORS, które dodają tylko Access-Control-Allow-Origindo określonych adresów URL, często są przez to przerywane.


Oczywiście udzielenie pozwolenia przez CORS jest czymś, co Bob zrobiłby tylko wtedy, gdy:

  • Dane nie były prywatne lub
  • Mallory był zaufany

Ale ja nie jestem Bobem!

Mallory nie ma standardowego mechanizmu dodawania tego nagłówka, ponieważ musi on pochodzić ze strony internetowej Boba, nad którą ona nie kontroluje.

Jeśli Bob uruchamia publiczny interfejs API, może istnieć mechanizm włączający CORS (na przykład przez sformatowanie żądania w określony sposób lub opcja konfiguracji po zalogowaniu się do witryny portalu deweloperów dla witryny Roberta). Będzie to jednak musiał być mechanizm wdrożony przez Boba. Mallory mogła przeczytać dokumentację w witrynie Boba, aby sprawdzić, czy coś jest dostępne, lub porozmawiać z Bobem i poprosić go o wdrożenie CORS.


Komunikaty o błędach zawierające wzmiankę „Odpowiedź na inspekcję wstępną”

Niektóre żądania z różnych źródeł są wstępnie sprawdzane .

Dzieje się tak, gdy (z grubsza mówiąc) próbujesz wysłać żądanie między źródłami, które:

  • Obejmuje dane uwierzytelniające, takie jak pliki cookie
  • Nie można go wygenerować za pomocą zwykłego formularza HTML (np. Ma niestandardowe nagłówki lub typ zawartości, którego nie można użyć w formularzu enctype).

Jeśli robisz coś poprawnie, co wymaga inspekcji wstępnej

W takich przypadkach reszta tej odpowiedzi nadal ma zastosowanie, ale musisz również upewnić się, że serwer może nasłuchiwać żądania wstępnego (które będzie OPTIONS(a nie GET, POSTlub cokolwiek próbujesz wysłać) i odpowiedzieć na nie z odpowiednimi uprawnieniami Access-Control-Allow-Originnagłówek, ale także Access-Control-Allow-Methodsi Access-Control-Allow-Headersaby zezwolić na określone metody lub nagłówki HTTP.

Jeśli przez pomyłkę uruchamiasz inspekcję wstępną

Czasami ludzie popełniają błędy, próbując tworzyć żądania Ajax, a czasami powodują one potrzebę przeprowadzenia inspekcji wstępnej. Jeśli interfejs API jest przeznaczony do zezwalania na żądania między źródłami, ale nie wymaga niczego, co wymagałoby inspekcji wstępnej, może to spowodować przerwanie dostępu.

Typowe błędy, które to powodują, obejmują:

  • próbuje umieścić Access-Control-Allow-Origini inne nagłówki odpowiedzi CORS na żądanie. Te nie należą do żądania, nie robią nic pomocnego (jaki byłby sens systemu uprawnień, w którym mógłbyś udzielić sobie pozwolenia?) I muszą pojawić się tylko w odpowiedzi.
  • próba umieszczenia Content-Type: application/jsonnagłówka w żądaniu GET, które nie ma treści żądania, aby opisać zawartość (zwykle gdy autor myli Content-Typei Accept).

W każdym z tych przypadków usunięcie dodatkowego nagłówka żądania często wystarczy, aby uniknąć konieczności przeprowadzenia inspekcji wstępnej (co rozwiąże problem podczas komunikacji z interfejsami API, które obsługują proste żądania, ale nie są wstępnie sprawdzane).


Nieprzezroczyste odpowiedzi

Czasami musisz wysłać żądanie HTTP, ale nie musisz czytać odpowiedzi. np. jeśli wysyłasz wiadomość dziennika na serwer w celu nagrania.

Jeśli korzystasz z fetchinterfejsu API (zamiast XMLHttpRequest), można skonfigurować, aby nie spróbować użyć CORS.

Zauważ, że to nie pozwoli ci zrobić niczego, do czego potrzebujesz CORS. Nie będziesz w stanie odczytać odpowiedzi. Nie będzie można złożyć wniosku wymagającego inspekcji wstępnej.

Pozwoli Ci to wykonać proste żądanie, nie zobaczyć odpowiedzi i nie wypełnić Developer Console komunikatami o błędach.

Jak to zrobić, wyjaśniono w komunikacie o błędzie Chrome wyświetlanym podczas wysyłania żądania przy użyciu fetchi nie uzyskujesz pozwolenia na wyświetlenie odpowiedzi za pomocą CORS:

Dostęp do pobierania z „ https://example.com/źródła pochodzenia” https://example.netzostał zablokowany przez zasady CORS: Brak Access-Control-Allow-Originnagłówka „ ” w żądanym zasobie. Jeśli nieprzezroczysta odpowiedź spełnia Twoje potrzeby, ustaw tryb żądania na „bez elementów”, aby pobrać zasób z wyłączonym mechanizmem CORS.

A zatem:

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

Alternatywy dla CORS

JSONP

Bob mógł również dostarczyć dane za pomocą hackowania, takiego jak JSONP, w ten sposób ludzie używali Ajax-a między źródłami, zanim pojawił się CORS.

Działa poprzez prezentowanie danych w postaci programu JavaScript, który wstrzykuje dane na stronę Mallory'ego.

Wymaga, aby Mallory ufał Bobowi, że nie dostarczy złośliwego kodu.

Zwróć uwagę na wspólny motyw: witryna dostarczająca dane musi informować przeglądarkę, że strona trzecia może uzyskać dostęp do danych, które wysyła do przeglądarki.

Ponieważ JSONP działa poprzez dołączenie <script>elementu w celu załadowania danych w postaci programu JavaScript, który wywołuje funkcję już na stronie, próba użycia techniki JSONP na adresie URL, który zwraca kod JSON, kończy się niepowodzeniem - zwykle z błędem CORB - ponieważ JSON nie jest JavaScriptem.

Przenieś dwa zasoby do jednego źródła

Jeśli dokument HTML, w którym działa JS, a żądany adres URL ma to samo źródło (ma ten sam schemat, nazwę hosta i port), to te same zasady pochodzenia domyślnie przyznają uprawnienia. CORS nie jest potrzebny.

Pełnomocnik

Mallory mogłaby użyć kodu po stronie serwera do pobrania danych (które mogłaby następnie przekazać ze swojego serwera do przeglądarki Alicji przez HTTP jak zwykle).

Będzie to:

  • dodaj nagłówki CORS
  • przekonwertuj odpowiedź na JSONP
  • istnieją w tym samym źródle co dokument HTML

Ten kod po stronie serwera może być napisany i obsługiwany przez stronę trzecią (taką jak CORS Anywhere). Zwróć uwagę na konsekwencje związane z prywatnością: strona trzecia może monitorować, kto jest pełnomocnikiem na swoich serwerach.

Bob nie musiałby udzielać żadnych uprawnień, aby to się stało.

Nie ma tu żadnych konsekwencji dla bezpieczeństwa, ponieważ jest to tylko między Mallory i Bobem. Bob nie może pomyśleć, że Mallory to Alice i przekazać Mallory dane, które powinny pozostać poufne między Alice i Bobem.

W związku z tym Mallory może używać tej techniki tylko do odczytywania danych publicznych .

Pamiętaj jednak, że pobieranie treści z cudzej witryny internetowej i wyświetlanie jej na własną rękę może stanowić naruszenie praw autorskich i stanowić podstawę do podjęcia kroków prawnych.

Pisanie czegoś innego niż aplikacja internetowa

Jak wspomniano w sekcji „Dlaczego zasada tego samego źródła dotyczy tylko kodu JavaScript na stronie internetowej”, możesz uniknąć SOP, nie pisząc kodu JavaScript na stronie internetowej.

Nie oznacza to, że nie możesz dalej używać JavaScript i HTML, ale możesz je rozpowszechniać za pomocą innego mechanizmu, takiego jak Node-WebKit lub PhoneGap.

Rozszerzenia przeglądarki

Rozszerzenie przeglądarki może wstawić nagłówki CORS w odpowiedzi przed zastosowaniem tej samej zasady pochodzenia.

Mogą one być przydatne przy programowaniu, ale nie są praktyczne w przypadku witryny produkcyjnej (proszenie każdego użytkownika witryny o zainstalowanie rozszerzenia przeglądarki, które wyłącza funkcję zabezpieczeń przeglądarki, jest nieuzasadnione).

Zwykle działają również tylko z prostymi żądaniami (niepowodzenie podczas obsługi żądań OPCJI inspekcji wstępnej).

Posiadanie odpowiedniego środowiska programistycznego z lokalnym serwerem programistycznym jest zwykle lepszym podejściem.


Inne zagrożenia bezpieczeństwa

Należy zauważyć, że SOP / CORS nie łagodzą ataków XSS , CSRF lub SQL Injection, które muszą być obsługiwane niezależnie.


Podsumowanie

  • Nie ma nic można zrobić w swoim kodu po stronie klienta, który pozwoli CORS dostęp do kogoś innego serwera.
  • Jeśli kontrolujesz serwer, żądanie jest wysyłane do: Dodaj do niego uprawnienia CORS.
  • Jeśli jesteś przyjazny osobie, która ją kontroluje: poproś ją, aby dodała do niej uprawnienia CORS.
  • Jeśli jest to usługa publiczna:
    • Przeczytaj ich dokumentację API, aby zobaczyć, co mówią o dostępie do niego za pomocą JavaScript po stronie klienta:
      • Mogą zalecić użycie określonych adresów URL
      • Mogą obsługiwać JSONP
      • Mogą w ogóle nie obsługiwać dostępu między źródłami z kodu po stronie klienta (może to być celowa decyzja ze względów bezpieczeństwa, zwłaszcza jeśli musisz przekazać spersonalizowany klucz API w każdym żądaniu).
    • Upewnij się, że nie uruchamiasz żądania inspekcji wstępnej, którego nie potrzebujesz. Interfejs API może przyznać uprawnienia do prostych żądań, ale nie dla żądań wstępnie sprawdzonych.
  • Jeśli żadne z powyższych nie ma zastosowania: poproś przeglądarkę, aby komunikowała się z Twoim serwerem, a następnie poproś serwer o pobranie danych z innego serwera i przekazanie ich dalej. (Istnieją również usługi hostowane przez inne firmy, które dołączają nagłówki CORS do publicznie dostępnych zasobów, z których można korzystać).
Quentin
źródło
Jeśli uruchomię lokalną sieć LAN i spróbuję załadować Ajax z adresu IP / URL, czy to zadziała? Jeszcze tego nie próbowałem. jako że mój serwer WWW odzyskuje dane json to MCU
Ciasto piekarz
@Ciastopiekarz - Obowiązują normalne te same / różne reguły pochodzenia. Obowiązują normalne reguły routingu sieciowego.
Quentin,
25
Najbardziej kompletna odpowiedź ja kiedykolwiek czytać, a nie tylko link o Cors ..
pungggi
@Quentin - Wow! +1! Więc rozumiem, że jeśli Alice używa rozszerzenia CORS, serwer uważa, że ​​jej wywołania http nie pochodzą z javascript, ale z rozszerzenia przeglądarki i traktuje to jak normalne żądanie tego samego źródła?
snippetkid
@snippetkid - Nie. W zwykłym przypadku serwer wyśle ​​nagłówki CORS w każdej odpowiedzi i nie przejmuje się tym, skąd pochodzi żądanie. Do obowiązków przeglądarki należy zezwolenie lub odmowa dostępu do danych do JS na podstawie nagłówków CORS w odpowiedzi. (Sprawy stają się / trochę / bardziej złożone na serwerze, jeśli chodzi o żądania inspekcji wstępnej)
Quentin
3

Serwer docelowy musi dopuszczać żądania między źródłami. Aby umożliwić przesyłanie ekspresowe, wystarczy obsłużyć żądanie opcji http:

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);
});
Daphoque
źródło
3

Ponieważ nie jest to wymienione w zaakceptowanej odpowiedzi.

  • Nie dotyczy to dokładnie tego pytania, ale może pomóc innym, którzy szukają tego problemu
  • To jest coś, co możesz zrobić w swoim kodzie klienta, aby w niektórych przypadkach zapobiec błędom CORS .

Możesz skorzystać z prostych żądań .
Aby wykonać „Proste żądania”, wniosek musi spełniać kilka warunków. Np jedynie pozwalając POST, GETi HEADsposób, jak tylko pozwala na pewien podane nagłówki (można znaleźć wszystkie warunki tutaj ).

Jeśli kod klienta nie ustawia w żądaniu nagłówków, których dotyczy problem (np. „Akceptuj”), z wartością poprawki, może się zdarzyć, że niektórzy klienci automatycznie ustawią te nagłówki na „niestandardowe” wartości, co spowoduje, że serwer nie zaakceptuje ich jako Proste żądanie - które spowoduje błąd CORS.

zwif
źródło
2

Dzieje się tak z powodu błędu CORS. CORS to skrót od Cross Origin Resource Sharing. W prostych słowach ten błąd występuje, gdy próbujemy uzyskać dostęp do domeny / zasobu z innej domeny.

Przeczytaj więcej na ten temat tutaj: Błąd CORS z jquery

Aby to naprawić, jeśli masz dostęp do innej domeny, będziesz musiał zezwolić na Access-Control-Allow-Origin na serwerze. Można to dodać w nagłówkach. Możesz to włączyć dla wszystkich żądań / domen lub określonej domeny.

Jak uzyskać działające żądanie wpisu dotyczące udostępniania zasobów między źródłami (CORS)

Te linki mogą pomóc

Wisznu
źródło
0

Ten problem z CORS nie był dalej rozwijany (z innych powodów).

Mam ten problem z innego powodu. Mój interfejs również zwraca błąd nagłówka „Access-Control-Allow-Origin”.

Po prostu wskazałem zły adres URL, więc ten nagłówek nie został poprawnie odzwierciedlony (w którym zakładałem, że tak było). localhost (front end) -> wywołanie niezabezpieczonego protokołu http (prawdopodobnie https), upewnij się, że punkt końcowy interfejsu API z interfejsu wskazuje na właściwy protokół.

morph85
źródło
0

Mam ten sam błąd w konsoli Chrome.

Mój problem polegał na tym, że próbowałem przejść do witryny za pomocą http://zamiast https://. Więc nie było nic do naprawienia, po prostu musiałem przejść do tej samej witryny za pomocą https.

Subhashi
źródło
0

Ten błąd kosztował mnie 2 dni. Sprawdziłem dziennik serwera, żądanie / odpowiedź opcji inspekcji wstępnej między przeglądarką Chrome / Edge a serwerem było w porządku. Głównym powodem jest to, że odpowiedź serwera GET / POST / PUT / DELETE dla XHTMLRequest musi mieć również następujący nagłówek:

access-control-allow-origin: origin  

„Pochodzenie” znajduje się w nagłówku żądania (przeglądarka doda je do żądania za Ciebie). na przykład:

Origin: http://localhost:4221

możesz dodać nagłówek odpowiedzi, taki jak następujący, aby zaakceptować dla wszystkich:

access-control-allow-origin: *  

lub nagłówek odpowiedzi dla konkretnego żądania, takiego jak:

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

Komunikat w przeglądarkach nie jest zrozumiały: „... Żądany zasób”

zauważ, że: CORS działa dobrze dla localhost. inny port oznacza inną domenę. jeśli pojawi się komunikat o błędzie, sprawdź konfigurację CORS po stronie serwera.

HungNM2
źródło
-1

Żądanie „Pobierz” z dołączonymi nagłówkami przekształca się w żądanie „Opcje”. Tak więc pojawiają się problemy z polityką Corsa. Musisz zaimplementować żądanie „Opcje” na swoim serwerze.

kira
źródło
-6

Powinieneś włączyć CORS, aby działał.

Perostek Balveda
źródło