Bezpieczne udostępnianie zasobów między domenami
Zasada dotycząca tego samego pochodzenia w przeglądarce blokuje odczyt zasobu z innego pochodzenia. Ten mechanizm uniemożliwia złośliwym witrynom odczytywanie danych z innych witryn, ale uniemożliwia też ich legalne wykorzystywanie.
Współczesne aplikacje internetowe często chcą pobierać zasoby z innego źródła, np. aby pobierać dane JSON z innej domeny lub wczytywać obrazy z innej witryny do elementu <canvas>
. Mogą to być zasoby publiczne, które powinny być dostępne dla wszystkich, ale są blokowane przez zasady dotyczące tego samego źródła. Deweloperzy korzystali z różnych obejść komunikatu o błędzie, np. z JSONP.
Mechanizm CORS rozwiązuje ten problem w sposób ustandaryzowany. Włączenie CORS pozwala serwerowi poinformować przeglądarkę, że może ona używać dodatkowego źródła.
Jak działa żądanie zasobu w przeglądarce?
Przeglądarka i serwer mogą wymieniać się danymi w sieci za pomocą protokołu HyperText Transfer Protocol (HTTP). HTTP określa reguły komunikacji między osobą wysyłającą żądanie a osobą odpowiadającą na nie, w tym informacje potrzebne do uzyskania zasobu.
Nagłówek HTTP negocjuje wymianę wiadomości między klientem a serwerem i jest używany do określania dostępu. Zarówno żądanie przeglądarki, jak i odpowiedź serwera są podzielone na nagłówek i treść.
Nagłówek
Informacje o wiadomości, takie jak typ lub kodowanie wiadomości. Nagłówek może zawierać różne informacje wyrażone jako pary klucz-wartość. Nagłówek żądania i nagłówek odpowiedzi zawierają różne informacje.
Przykładowy nagłówek żądania
Accept: text/html
Cookie: Version=1
Ten nagłówek jest odpowiednikiem stwierdzenia „Chcę otrzymywać w odpowiedzi kod HTML. Oto mój plik cookie.
Przykładowy nagłówek odpowiedzi
Content-Encoding: gzip
Cache-Control: no-store
Ten nagłówek jest odpowiednikiem stwierdzenia „Dane w tej odpowiedzi są kodowane za pomocą programu gzip. Nie przechowuj tego w pamięci podręcznej”.
Treść
Treść wiadomości. Może to być zwykły tekst, plik binarny obrazu, JSON, HTML lub wiele innych.
Jak działa CORS?
Zasada dotycząca tego samego pochodzenia mówi przeglądarce, aby blokowała żądania z wielu źródeł. Gdy potrzebujesz zasobu publicznego z innego źródła, serwer dostarczający zasób informuje przeglądarkę, że źródło wysyłające żądanie może uzyskać dostęp do tego zasobu. Przeglądarka to pamięta i pozwala je na udostępnianie zasobów między domenami.
Krok 1. Żądanie klienta (przeglądarki)
Gdy przeglądarka wysyła żądanie z innej domeny, dodaje nagłówek Origin
z bieżącym źródłem (schemat, host i port).
Krok 2. Odpowiedź serwera
Gdy serwer zobaczy ten nagłówek i zechce zezwolić na dostęp, doda do odpowiedzi nagłówek Access-Control-Allow-Origin
, podając w nim źródło żądania (lub *
, aby zezwolić na dowolne źródło).
Krok 3. Przeglądarka otrzymuje odpowiedź
Gdy przeglądarka zobaczy tę odpowiedź z odpowiednim nagłówkiem Access-Control-Allow-Origin
, udostępni dane odpowiedzi stronie klienta.
Udostępnianie danych logowania za pomocą CORS
Ze względu na ochronę prywatności współdzielenie zasobów pomiędzy serwerami z różnych domen jest zwykle używane w przypadku anonimowych żądań, w których nie jest identyfikowany podmiot przesyłający żądanie. Jeśli chcesz wysyłać pliki cookie podczas korzystania z CORS, które mogą identyfikować nadawcę, musisz dodać do żądania i odpowiedzi dodatkowe nagłówki.
Żądanie
Dodaj credentials: 'include'
do opcji pobierania, tak jak w przykładzie poniżej.
Obejmuje to plik cookie z żądaniem w takiej postaci:
fetch('https://example.com', {
mode: 'cors',
credentials: 'include'
})
Odpowiedź
Access-Control-Allow-Origin
musi mieć konkretną wartość pochodzenia (bez symbolu wieloznacznego *
), a Access-Control-Allow-Credentials
musi mieć wartość true
.
HTTP/1.1 200 OK
Access-Control-Allow-Origin: https://example.com
Access-Control-Allow-Credentials: true
żądania wstępne w przypadku złożonych wywołań HTTP;
Gdy aplikacja internetowa wysyła złożone żądanie HTTP, przeglądarka dodaje żądanie wstępne na początku łańcucha żądań.
Specyfikacja CORS definiuje złożone żądanie w ten sposób:
- żądanie, które używa metod innych niż GET, POST lub HEAD;
- żądanie zawierające nagłówki inne niż
Accept
,Accept-Language
lubContent-Language
; - Żądanie, które ma nagłówek
Content-Type
inny niżapplication/x-www-form-urlencoded
,multipart/form-data
lubtext/plain
.
Przeglądarki automatycznie tworzą wszystkie niezbędne żądania wstępne i wysyłają je przed rzeczywistą wiadomością żądania. Żądanie procesu wstępnego to żądanie OPTIONS
, takie jak w tym przykładzie:
OPTIONS /data HTTP/1.1
Origin: https://example.com
Access-Control-Request-Method: DELETE
Po stronie serwera aplikacja odbierająca żądanie odpowiada na żądanie wstępne, podając informacje o akceptowanych przez aplikację metodach z tego źródła:
HTTP/1.1 200 OK
Access-Control-Allow-Origin: https://example.com
Access-Control-Allow-Methods: GET, DELETE, HEAD, OPTIONS
Odpowiedź serwera może też zawierać nagłówek Access-Control-Max-Age
określający czas (w sekundach) buforowania wyników kontroli wstępnych. Dzięki temu klient może wysyłać wiele złożonych żądań bez konieczności powtarzania żądania procesu wstępnego.