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

Feb 22 2016

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?

Odpowiedzi

224 Quentin Feb 22 2016 at 19:26

tl; dr - Na końcu i nagłówkach odpowiedzi znajduje się podsumowanie, aby ułatwić znalezienie odpowiednich części. Zalecane jest jednak przeczytanie wszystkiego, ponieważ zapewnia przydatne tło do zrozumienia, dlaczego , dzięki temu ł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 kwestie 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 stronę 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 ma 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 odczytaniu przez JavaScript danych zwróconych przez witrynę internetową Boba (do której Bob i Alicja nie chcą, aby Mallory miał do nich 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.


Dlaczego ta sama polityka pochodzenia dotyczy tylko języka 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ę . Instalacja 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 w tym zasobie, 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.

Specyfika sposobu, w jaki Bob ustawia ten nagłówek odpowiedzi, zależy 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.

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 omijane.


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 poprzez sformatowanie żądania w określony sposób lub opcję 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 również Access-Control-Allow-Methodsi Access-Control-Allow-Headersaby umożliwić specyficzne metody HTTP lub nagłówków.

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ś przyznać sobie pozwolenie?) 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 wykonywania 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.

Zwróć uwagę, ż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 na proste żądanie, nie zobaczenie 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 „brak 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 z różnych źródeł, 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, zakoń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 ma zastosowanie tylko do języka 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 nierozsądne).

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ą o dodanie do niej uprawnień 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ć).
4 Daphoque Sep 09 2016 at 17:45

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);
});
3 zwif Nov 09 2017 at 18:37

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 poprawioną wartością, 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.

2 Vishnu Feb 22 2016 at 19:32

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

morph85 Dec 17 2018 at 13:40

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, aby ten nagłówek nie był poprawnie odzwierciedlony (w którym zakładałem, że tak). localhost (front end) -> wywołanie niezabezpieczonego http (przypuszczalnie https), upewnij się, że punkt końcowy interfejsu API z interfejsu wskazuje na właściwy protokół.

Subhashi Feb 11 2020 at 18:02

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://. Nie było więc nic do naprawienia, wystarczyło przejść do tej samej witryny za pomocą https.

HungNM2 Aug 20 2020 at 09:13

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 jest niejasny do zrozumienia: „... Żą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.