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:4300
w 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 XMLHttpRequest
i 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-Origin
HTTP 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.
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-Origin
do 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
, POST
lub cokolwiek próbujesz wysłać) i odpowiedzieć na nie z odpowiednimi uprawnieniami Access-Control-Allow-Origin
nagłówek, ale także Access-Control-Allow-Methods
i Access-Control-Allow-Headers
aby 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-Origin
i 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/json
nagłówka w żądaniu GET, które nie ma treści żądania, aby opisać zawartość (zwykle gdy autor myli Content-Type
i 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 fetch
interfejsu 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 fetch
i nie uzyskujesz pozwolenia na wyświetlenie odpowiedzi za pomocą CORS:
Dostęp do pobierania z „ https://example.com/
źródła pochodzenia” https://example.net
został zablokowany przez zasady CORS: Brak Access-Control-Allow-Origin
nagłó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ć).