Współdzielenie zasobów pomiędzy serwerami z różnych domen (CORS)

Mariko Kosaka

Opublikowano: 5 listopada 2018 r.

Zasada takiego samego pochodzenia w przeglądarce blokuje odczytywanie zasobów z innego źródła. Ten mechanizm uniemożliwia złośliwym witrynom odczytywanie danych z innych witryn, ale też blokuje uzasadnione zastosowania.

Nowoczesne aplikacje internetowe często chcą pobierać zasoby z innego źródła, np. 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 każdego, ale zasada takiego samego pochodzenia blokuje ich użycie. Deweloperzy historycznie stosowali obejścia, takie jak JSONP.

Współdzielenie zasobów pomiędzy serwerami z różnych domen (CORS) rozwiązuje ten problem w standardowy sposób. Włączenie CORS umożliwia serwerowi poinformowanie przeglądarki, że może ona używać dodatkowego źródła.

Jak działa żądanie zasobu w internecie?

Ilustracja żądania klienta i odpowiedzi serwera.

Przeglądarka i serwer mogą wymieniać dane przez sieć za pomocą protokołu przesyłania hipertekstu (HTTP). HTTP określa reguły komunikacji między osobą wysyłającą żądanie a osobą odpowiadającą, w tym informacje potrzebne do uzyskania zasobu.

Nagłówek HTTP negocjuje wymianę wiadomości między klientem a serwerem i służy do określania dostępu. Zarówno żądanie przeglądarki, jak i odpowiedź serwera są podzielone na nagłówek i treść.

Informacje o wiadomości, takie jak jej typ lub kodowanie. 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 równoznaczny z komunikatem „Chcę otrzymać 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 równoznaczny z komunikatem „Dane w tej odpowiedzi są zakodowane za pomocą gzip. Nie zapisuj ich w pamięci podręcznej”.

Treść

Sama wiadomość. Może to być zwykły tekst, plik binarny obrazu, JSON, HTML lub wiele innych formatów.

Jak działa CORS?

Zasada takiego samego pochodzenia informuje przeglądarkę, aby blokowała żądania dotyczące zasobów ze współdzieleniem. Gdy potrzebujesz zasobu publicznego z innego źródła, serwer udostępniający zasób informuje przeglądarkę, że źródło wysyłające żądanie może uzyskać dostęp do jego zasobu. Przeglądarka zapamiętuje to i zezwala na współdzielenie zasobów z innej domeny w przypadku tego zasobu.

Krok 1. Żądanie klienta (przeglądarki)

Gdy przeglądarka wysyła żądanie współdzielenia zasobów, dodaje nagłówek Origin z bieżącym źródłem (schematem, hostem i portem).

Krok 2. Odpowiedź serwera

Gdy serwer zobaczy ten nagłówek i będzie chciał zezwolić na dostęp, doda do odpowiedzi nagłówek Access-Control-Allow-Origin określający ź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 witrynie klienta.

Udostępnianie danych logowania za pomocą CORS

Ze względu na ochronę prywatności CORS jest zwykle używany w przypadku żądań anonimowych, w których osoba wysyłająca żądanie nie jest identyfikowana. Jeśli chcesz wysyłać pliki cookie podczas korzystania z CORS, które mogą identyfikować nadawcę, musisz dodać dodatkowe nagłówki do żądania i odpowiedzi.

Żądanie

Dodaj credentials: 'include' do opcji pobierania, jak w tym przykładzie. Obejmuje to plik cookie z żądaniem w ten sposób:

fetch('https://example.com', {
  mode: 'cors',
  credentials: 'include'
})

Odpowiedź

Access-Control-Allow-Origin musi być ustawiony na konkretne źródło (bez symbolu wieloznacznego *), a Access-Control-Allow-Credentials musi być ustawiony na true.

HTTP/1.1 200 OK
Access-Control-Allow-Origin: https://example.com
Access-Control-Allow-Credentials: true

Żądania wstępne dotyczące złożonych wywołań HTTP

Gdy aplikacja internetowa wysyła złożone żądanie HTTP, przeglądarka dodaje na początku łańcucha żądań żądanie wstępne.

Specyfikacja CORS definiuje złożone żądanie w ten sposób:

  • Żądanie, które używa metod innych niż GET, POST lub HEAD.
  • Żądanie, które zawiera nagłówki inne niż Accept, Accept-Language lub Content-Language.
  • Żądanie, które ma nagłówek Content-Type inny niż application/x-www-form-urlencoded, multipart/form-data lub text/plain.

Przeglądarki automatycznie tworzą wszystkie niezbędne żądania wstępne i wysyłają je przed rzeczywistą wiadomością żądania. Żądanie wstępne to żądanie OPTIONS, 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 informacjami o metodach, które aplikacja akceptuje 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, aby określić czas w sekundach, przez jaki mają być przechowywane w pamięci podręcznej wyniki żądania wstępnego. Umożliwia to klientowi wysyłanie wielu złożonych żądań bez konieczności powtarzania żądania wstępnego.