Jak działa nagłówek Access-Control-Allow-Origin?

Najwyraźniej całkowicie źle zrozumiałem jego semantykę. Myślałem o czymś takim:

  1. klient pobiera kod javascript MyCode.js od http://siteA - pochodzenie.
  2. nagłówek odpowiedzi MyCode.js zawiera Access-Control-Allow-Origin: http://siteB , co myślałem, że oznacza to MyCode.js mógł tworzyć odniesienia do strony B.
  3. Klient uruchamia pewną funkcjonalność MyCode.js, które z kolei składają wnioski na http://siteB, co powinno być w porządku, mimo że są to wnioski wzajemne.

Cóż, mylę się. To w ogóle tak nie działa. Tak więc przeczytałem Cross-origin resource sharing i próbowałem przeczytać Cross-Origin Resource Sharing w zaleceniu w3c

Jedno jest pewne-nadal nie rozumiem, jak mam używać tego nagłówka.

Mam pełną kontrolę zarówno nad stroną A jak i stroną B. Jak włączyć kod javascript pobrany z strona A, aby uzyskać dostęp do zasobów na stronie B za pomocą tego nagłówka?

P. S.

Nie chcę używać JSONP.

Author: Sujania, 2012-05-17

11 answers

Access-Control-Allow-Origin jest nagłówkiem CORS (Cross-Origin Resource Sharing) .

Gdy witryna A próbuje pobrać zawartość z witryny B, witryna B może wysłać nagłówek odpowiedzi Access-Control-Allow-Origin, aby poinformować przeglądarkę, że zawartość tej strony jest dostępna dla określonych źródeł. (An origin jest domeną , plus schemat i numer portu.) Domyślnie strony witryny B są niedostępne dla żadnego innego źródła ; użycie nagłówka Access-Control-Allow-Origin otwiera drzwi do dostępu między źródłami przez określone proszę o pochodzenie.

Jeśli strona B chce udostępnić witrynie a, strona B powinna obsługiwać swoje strony z nagłówkiem odpowiedzi:
Access-Control-Allow-Origin: http://siteA.com

Nowoczesne przeglądarki nie będą blokować żądań między domenami wprost. Jeśli witryna A zażąda strony z witryny B, przeglądarka pobierze żądaną stronę na poziomie sieci i sprawdzi, czy nagłówki odpowiedzi zawierają witrynę a jako dozwoloną domenę żądającego. Jeżeli strona B nie wskazała, że strona A jest dozwolona aby uzyskać dostęp do tej strony, przeglądarka uruchomi Zdarzenie XMLHttpRequest's error i odmówi danych odpowiedzi na żądany kod JavaScript.

Nie - proste żądania

To, co dzieje się na poziomie sieci, może być nieco bardziej złożone niż wyjaśniono powyżej. Jeśli żądanie jest żądaniem "non-simple" , przeglądarka najpierw wysyła żądanie opcji "preflight" bez danych, aby sprawdzić, czy serwer zaakceptuje żądanie. Żądanie nie jest proste, gdy albo (lub oba):
    W 2007 roku firma została założona w 2008 roku przez firmę Garmin.]}
  • używanie Nie prostych nagłówków żądań; jedynymi prostymi nagłówkami żądań są:
    • Accept
    • Accept-Language
    • Content-Language
    • Content-Type (jest to proste tylko wtedy, gdy jego wartość jest application/x-www-form-urlencoded, multipart/form-data, lub text/plain)

Jeśli serwer odpowie na opcje z odpowiednimi nagłówkami odpowiedzi (Access-Control-Allow-Headers dla nagłówków non-simple, Access-Control-Allow-Methods dla czasowników non-simple), że dopasuj nagłówki non-simple i / lub non-simple, a następnie przeglądarka wysyła rzeczywiste żądanie.

Jeśli strona A chce wysłać zapytanie PUT dla /somePage, z nieprostą Content-Type wartością application/json, przeglądarka najpierw wyśle żądanie inspekcji wstępnej:
OPTIONS /somePage HTTP/1.1
Origin: http://siteA.com
Access-Control-Request-Method: PUT
Access-Control-Request-Headers: Content-Type

Zauważ, że Access-Control-Request-Method i Access-Control-Request-Headers są dodawane przez przeglądarkę automatycznie; nie musisz ich dodawać. Ta opcja preflight pobiera pomyślne nagłówki odpowiedzi:

Access-Control-Allow-Origin: http://siteA.com
Access-Control-Allow-Methods: GET, POST, PUT
Access-Control-Allow-Headers: Content-Type

Podczas wysyłania rzeczywistego żądania (po przeprowadzeniu inspekcji wstępnej), zachowanie jest identyczne z zachowaniem obsługi prostego żądania. Innymi słowy, nieproste żądanie, którego Inspekcja wstępna się powiodła, jest traktowane tak samo jak zwykłe żądanie (tzn. serwer musi jeszcze raz wysłać Access-Control-Allow-Origin dla rzeczywistej odpowiedzi).

Przeglądarki wysyłają rzeczywiste żądanie:

PUT /somePage HTTP/1.1
Origin: http://siteA.com
Content-Type: application/json

{ "myRequestContent": "JSON is so great" }
Serwer odsyła Access-Control-Allow-Origin, tak jak w przypadku prostego żądania:
Access-Control-Allow-Origin: http://siteA.com

Zobacz zrozumienie XMLHttpRequest nad CORS dla trochę więcej informacji na temat nie prostych wniosków.

 1060
Author: apsillers,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2017-05-23 11:47:28

[6]}Cross-Origin Request Sharing - CORS (Aka Cross-Domain AJAX request) to problem, który może napotkać większość programistów internetowych, zgodnie z zasadami tego samego pochodzenia, przeglądarki ograniczają JavaScript Klienta w piaskownicy bezpieczeństwa, Zwykle JS nie może bezpośrednio komunikować się ze zdalnym serwerem z innej domeny. W przeszłości programiści stworzyli wiele trudnych sposobów na osiągnięcie żądania zasobów między domenami, najczęściej używanymi sposobami są: {]}

  1. użyj Flash/Silverlight lub po stronie serwera jako " proxy" komunikować się z pilotem.
  2. JSON With Padding (JSONP ).
  3. osadza zdalny serwer w ramce iframe i komunikuje się poprzez fragment lub window.name, patrz tutaj .

Te trudne sposoby mają mniej więcej pewne problemy, na przykład JSONP może spowodować dziurę w bezpieczeństwie, jeśli deweloperzy po prostu "eval" go, a #3 powyżej, chociaż to działa, obie domeny powinny budować ścisły kontrakt między sobą, to ani elastyczne, ani eleganckie IMHO:) {]}

W3C miał wprowadzono Cross-Origin Resource Sharing (CORS) jako standardowe rozwiązanie, aby zapewnić bezpieczny, elastyczny i zalecany standardowy sposób rozwiązania tego problemu.

Mechanizm

Z wysokiego poziomu możemy po prostu uznać, że CORS jest umową między Klientem AJAX wywołania z domeny a i strony hostowanej na domenie B, typowy Cross-Origin żądanie / odpowiedź będzie:

DomainA AJAX request headers

Host DomainB.com
User-Agent Mozilla/5.0 (Windows NT 6.1; WOW64; rv:2.0) Gecko/20100101 Firefox/4.0
Accept text/html,application/xhtml+xml,application/xml;q=0.9,*/*;q=0.8,application/json
Accept-Language en-us;
Accept-Encoding gzip, deflate
Keep-Alive 115
Origin http://DomainA.com 

Odpowiedź DomainB nagłówki

Cache-Control private
Content-Type application/json; charset=utf-8
Access-Control-Allow-Origin DomainA.com
Content-Length 87
Proxy-Connection Keep-Alive
Connection Keep-Alive

Niebieskie części, które zaznaczyłem powyżej, to fakty kernal, nagłówek żądania" Origin "wskazuje, skąd pochodzi żądanie cross-origin lub żądanie inspekcji wstępnej", nagłówek odpowiedzi "Access-Control-Allow-Origin" wskazuje, że ta strona pozwala na zdalne żądanie z domeny (jeśli wartość to * indicate pozwala na zdalne żądania z dowolnej domeny).

Jak wspomniałem powyżej, W3 zaleca przeglądarce zaimplementować "preflight request " przed złożeniem Cross-Origin HTTP request, w skrócie jest to http OPTIONS request:

OPTIONS DomainB.com/foo.aspx HTTP/1.1

If foo.aspx obsługuje opcje http verb, może zwrócić odpowiedź jak poniżej:

HTTP/1.1 200 OK
Date: Wed, 01 Mar 2011 15:38:19 GMT
Access-Control-Allow-Origin: http://DomainA.com
Access-Control-Allow-Methods: POST, GET, OPTIONS, HEAD
Access-Control-Allow-Headers: X-Requested-With
Access-Control-Max-Age: 1728000
Connection: Keep-Alive
Content-Type: application/json

Tylko jeśli odpowiedź zawiera "Access-Control-Allow-Origin", a jej wartością jest "*" lub zawiera domenę, która przesłała żądanie CORS, spełniając ten warunek mandtory przeglądarka wyśle rzeczywiste żądanie między domenami i wywoła wynik w pamięci podręcznej " Preflight-Result-Cache".

Blogowałem o CORS trzy lata temu: AJAX Cross-Origin HTTP request

 104
Author: Wayne Ye,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2016-07-28 09:01:23

Pytanie jest trochę za Stare, aby odpowiedzieć, ale zamieszczam to w przyszłości odniesienia do tego pytania.

[20]}według tego artykułu Mozilla Developer Network,
[20]}zasób wysyła żądanie HTTP cross-origin , gdy żąda zasobu z innej domeny lub portu niż ten, do którego służy pierwszy zasób.

Tutaj wpisz opis obrazka

Strona HTML serwowana z http://domain-a.com tworzy <img> src wniosek o http://domain-b.com/image.jpg.
Wiele stron w sieci ładuje dziś zasoby takie jak arkusze stylów CSS , obrazy i Skrypty z oddzielnych domen (więc powinno być fajnie).

Polityka Tego Samego Pochodzenia

Ze względów bezpieczeństwa przeglądarki ograniczają żądania HTTP inicjowane ze skryptów .
Na przykład, XMLHttpRequest i Fetch postępują zgodnie z Polityką tego samego pochodzenia.
Tak więc, aplikacja internetowa używająca XMLHttpRequest lub Fetch może tylko wykonaj żądania HTTP do własnej domeny .

Cross-Origin Resource Sharing (CORS)

Aby ulepszyć aplikacje internetowe, Programiści zwrócili się do dostawców przeglądarek o zezwolenie na żądania między domenami.

Mechanizm Cross-Origin Resource Sharing (CORS) daje serwerom www kontrolę dostępu między domenami , które umożliwiają bezpieczne przesyłanie danych między domenami.
Współczesne przeglądarki używają CORS w kontenerze API - np. XMLHttpRequest lub Fetch - w celu ograniczenia ryzyka cross-origin żądań HTTP.

Jak działa CORS (Access-Control-Allow-Origin header)

Wikipedia:

Standard CORS opisuje nowe nagłówki HTTP, które zapewniają przeglądarkom i serwerom możliwość żądania zdalnych adresów URL tylko wtedy, gdy mają uprawnienia.

Chociaż niektóre walidacje i autoryzacje mogą być wykonywane przez Serwer, jest ogólnie obowiązkiem przeglądarki , aby wspierać te nagłówki i szanować nakładają ograniczenia.

Przykład

  1. Przeglądarka wysyła zapytanie OPTIONS z nagłówkiem Origin HTTP.

    Wartością tego nagłówka jest domena, która obsługiwała Stronę nadrzędną. Gdy strona z http://www.example.com próbuje uzyskać dostęp do danych użytkownika w service.example.com, następujący nagłówek żądania zostanie wysłany do service.example.com:

    Pochodzenie: http://www.example.com

  2. Serwer na service.example.com może odpowiedzieć:

    • An Access-Control-Allow-Origin (ACAO) nagłówek w odpowiedzi wskazujący, które miejsca pochodzenia są dozwolone.
      Na przykład:

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

    • Strona błędu, jeśli serwer nie zezwala na żądanie cross-origin

    • Nagłówek Access-Control-Allow-Origin (ACAO) z symbolem wieloznacznym, który pozwala na wszystkie domeny:

      Access-Control-Allow-Origin: *

 35
Author: Trix,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2017-03-05 06:39:53

Jeśli chcesz po prostu przetestować aplikację cross domain, w której przeglądarka blokuje twoje żądanie, możesz po prostu otworzyć przeglądarkę w trybie niebezpiecznym i przetestować aplikację bez zmiany kodu i bez uczynienia kodu niebezpiecznym. Z MAC OS można to zrobić z linii terminala:

open -a Google\ Chrome --args --disable-web-security --user-data-dir
 7
Author: Maurizio Brioschi,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2017-02-22 16:32:30

Używając React i Axios, Dołącz łącze proxy do adresu URL i dodaj nagłówek, jak pokazano poniżej

https://cors-anywhere.herokuapp.com/ + Your API URL

Po prostu dodając link Proxy będzie działać, ale może również rzucić błąd dla braku dostępu ponownie. Dlatego lepiej dodać nagłówek, jak pokazano poniżej.

axios.get(`https://cors-anywhere.herokuapp.com/[YOUR_API_URL]`,{headers: {'Access-Control-Allow-Origin': '*'}})
      .then(response => console.log(response:data);
  }
 7
Author: Dhaval Jardosh,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2017-10-16 15:53:24

1. Klient pobiera kod javascript MyCode.js z http://siteA - pochodzenie.

Kod, który pobiera - Twój znacznik HTML script lub xhr z javascript lub cokolwiek innego-pochodzi z, powiedzmy, http://siteZ . I, gdy przeglądarka zażąda MyCode.js, wysyła nagłówek Origin: mówiący " Origin: http://siteZ ", ponieważ widać, że prosisz o siteA i siteZ!= siteA. (Nie można zatrzymać ani ingerować w to.)

2. Nagłówek odpowiedzi MyCode.js zawiera Access-Control-Allow-Origin: http://siteB , co myślałem, że oznacza to MyCode.js mógł tworzyć odniesienia do strony B.

Nie. Oznacza to, że tylko siteB może wykonać to żądanie. Więc twoja prośba o MyCode.zamiast tego js z siteZ pobiera błąd, a przeglądarka zazwyczaj nie daje nic. Ale jeśli sprawisz, że twój serwer zwróci A-C-A-o: siteZ, otrzymasz MyCode.js . Lub jeśli to wysyła"*", to zadziała, to wpuści wszystkich. Lub jeżeli serwer zawsze wysyła łańcuch z nagłówka Origin:... ale... dla bezpieczeństwa, jeśli boisz się hakerów, Twój serwer powinien zezwalać tylko na origins na krótkiej liście, które mogą składać te żądania.

Wtedy MyCode.js pochodzi z siteA. Kiedy wysyła żądania do siteB, wszystkie są cross-origin, przeglądarka wysyła Origin: siteA, a siteB musi wziąć siteA, rozpoznać, że znajduje się na krótkiej liście dozwolonych żądań i odeślij A-C-a-o: siteA. Dopiero wtedy przeglądarka pozwoli Twojemu skryptowi uzyskać wynik tych żądań.

 6
Author: OsamaBinLogin,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2016-02-27 01:37:43

Pracuję z Expressem 4 i node 7.4 i angular, miałem ten sam problem pomagam w tym:
a) strona serwera: w aplikacji plik.js daję nagłówki do wszystkich odpowiedzi typu:

app.use(function(req, res, next) {  
      res.header('Access-Control-Allow-Origin', req.headers.origin);
      res.header("Access-Control-Allow-Headers", "Origin, X-Requested-With, Content-Type, Accept");
      next();
 });  

To musi mieć przed wszystkimi routerami .
Widziałem wiele dodanych nagłówków:

res.header("Access-Control-Allow-Headers","*");
res.header('Access-Control-Allow-Credentials', true);
res.header('Access-Control-Allow-Methods', 'GET,PUT,POST,DELETE');

Ale nie potrzebuję tego,
b) po stronie klienta: w send ajax musisz dodać: "withCredentials: true", jak:

$http({
     method: 'POST',
     url: 'url, 
     withCredentials: true,
     data : {}
   }).then(function(response){
        // code  
   }, function (response) {
         // code 
   });
Powodzenia.
 5
Author: izik f,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2017-02-06 08:19:11

Ilekroć zaczynam myśleć o CORS, moja intuicja co do tego, która strona hostuje nagłówki, jest niepoprawna, tak jak opisałeś w swoim pytaniu. Dla mnie pomaga myślenie o celu tej samej polityki pochodzenia.

Celem tej samej polityki pochodzenia jest ochrona przed złośliwym JavaScript na siteA.com dostęp do prywatnych informacji, z którymi chcesz się dzielić siteB.com. bez tej samej polityki pochodzenia, JavaScript napisany przez autorów siteA.com może sprawić, że Twoje przeglądarka wysyła żądania do siteB.com, korzystanie z plików cookie uwierzytelniających dla siteB.com w ten sposób, siteA.com może ukraść tajne informacje, którymi się dzielisz siteA.com.

Czasami trzeba pracować cross domain, czyli gdzie pojawia się CORS. Korsarz domainA.com, używając nagłówka Access-Control-Allow-Origin do wyświetlenia innych domen (domainB.com), które są zaufane do uruchamiania JavaScript, który może współdziałać z domainA.com.

Aby zrozumieć, która domena powinna służyć CORS nagłówki, rozważ to. Odwiedzasz malicious.com, który zawiera JavaScript, który próbuje wysłać żądanie cross domain do mybank.com. powinno być do mybank.com, nie malicious.com, aby zdecydować, czy ustawia nagłówki CORS, które rozluźniają tę samą politykę origin, pozwalając JavaScript z malicious.com do interakcji z nim. Gdyby było to możliwe dla malicous.com aby ustawić własne nagłówki CORS umożliwiające własny dostęp JavaScript do mybank.com, to całkowicie zniweczyłoby to samo pochodzenie Polityka.

Myślę, że powodem mojej złej intuicji jest punkt widzenia, który mam podczas tworzenia strony. Its my site, with all my JavaScript, dlatego nie robi nic złośliwego i to powinno być do me aby określić, które inne strony my JavaScript może wchodzić w interakcje z. Kiedy w rzeczywistości powinienem myśleć, które inne Strony JavaScript próbują wchodzić w interakcję z moją witryną i czy powinienem używać CORS, aby na to pozwolić?

 5
Author: Dom,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2018-01-28 18:47:01

Jeśli używasz PHP, spróbuj dodać następujący kod w pliku php:

Jeśli używasz localhost, spróbuj tego:

header("Access-Control-Allow-Origin: *");

Jeśli używasz zewnętrznych domen, takich jak serwer, spróbuj tego:

header("Access-Control-Allow-Origin: http://www.website.com");
 3
Author: Melvin Guerrero,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2017-01-18 15:30:06

Do dzielenia między źródłami, Ustaw nagłówek: 'Access-Control-Allow-Origin':'*';

Php: header('Access-Control-Allow-Origin':'*');

Węzeł: app.use('Access-Control-Allow-Origin':'*');

Pozwoli to na udostępnianie treści dla różnych domen.

 2
Author: user2923052,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2017-01-16 08:10:04

W Pythonie używałem Flask-CORS biblioteka z wielkim sukcesem. To sprawia, że radzenie sobie z Kors super łatwe i bezbolesne. Dodałem kod z dokumentacji biblioteki poniżej.

Instalowanie:

$ pip install -U flask-cors

Prosty przykład, który pozwala CORS dla wszystkich domen na wszystkich trasach:

from flask import Flask
from flask_cors import CORS

app = Flask(__name__)
CORS(app)

@app.route("/")
def helloWorld():
  return "Hello, cross-origin-world!"

Bardziej szczegółowe przykłady można znaleźć w dokumentacji. Użyłem prostego przykładu powyżej, aby ominąć problem CORS w aplikacji jonowej, którą buduję, aby uzyskać dostęp do oddzielny serwer flask.

 2
Author: agaidis,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2018-01-25 11:10:18