Deadly CORS, gdy źródłem jest http: // localhost

186

Utknąłem z tym problemem CORS, mimo że ustawiłem serwer (nginx / node.js) z odpowiednimi nagłówkami.

Widzę w okienku Sieć Chrome -> Nagłówki odpowiedzi:

Access-Control-Allow-Origin:http://localhost

co powinno załatwić sprawę.

Oto kod, którego teraz używam do testowania:

var xhr = new XMLHttpRequest();
xhr.onload = function() {
   console.log('xhr loaded');
};
xhr.open('GET', 'http://stackoverflow.com/');
xhr.send();

dostaję

XMLHttpRequest nie może załadować http://stackoverflow.com/ . Pochodzenie http: // localhost nie jest dozwolone przez Access-Control-Allow-Origin.

Podejrzewam, że jest to problem w skrypcie klienta, a nie w konfiguracji serwera ...

whadar
źródło
44
Nie, stackoverflow.com musi ustawić ten nagłówek, a nie ty. : x. Jaki byłby sens takiej samej polityki pochodzenia w innym przypadku.
Esailija,
3
Spróbuj uzyskać dostęp do skonfigurowanego serwera, aby nie przepełnić stosu. ;)
Nek
DOH! Czy istnieje sposób, aby powiedzieć chrome (lub innej przeglądarce), aby uzyskać zasób, nawet jeśli brakuje nagłówka, gdy moim źródłem jest localhost?
whadar
Uruchom kody w Chrome (20.0.1132.57, Windows 7), działa dobrze.
imwilsonxu
1
Jeśli używasz localhost z portem, ta odpowiedź zadziałała dla mnie serverfault.com/a/673551/238261 .
Nelu

Odpowiedzi:

230

Chrome nie obsługuje localhost dla żądań CORS (błąd otwarty w 2010 r., Oznaczony WontFix w 2014 r.).

Aby obejść ten problem, możesz użyć domeny typu lvh.me(która wskazuje na 127.0.0.1 podobnie jak localhost) lub uruchomić chrome z --disable-web-securityflagą (zakładając, że właśnie testujesz).

Amant
źródło
24
@greensuisse - to nie jest publikowanie na localhost. To delegowania z localhost, że jest problem.
Cheeso
9
Ten błąd jest nieprawidłowy (i został oznaczony jako taki - crbug.com/67743#c17 ). Komentarz Esailija jest poprawny, dodanie tych nagłówków do localhost nie magicznie zapewni ci dostępu do wszystkich innych stron. To zdalna witryna, która musi być obsługiwana z tymi nagłówkami.
Rob W
22
Po prostu spędziłem 2 godziny na testowaniu Chrome, aby stwierdzić, że działa on doskonale w przeglądarce Firefox.Grrrr...
FloatingRock
11
Inna opcja: edytuj plik hosts, aby lokalny. [Mysite] .com wskazywał na 127.0.0.1, a następnie pozwól, aby plik CORS zezwalał *. [Mysite] .com
tom
6
Z FireFoxem spotkałem ten sam problem. Mogłem to zrobić tylko na Edge! Fajny post, fantastyczny! :)
Luis Gouveia,
53

Zgodnie z odpowiedzią @ Beau Chrome nie obsługuje żądań CORS hostów lokalnych i nie ma w tym kierunku żadnych zmian.

Korzystam z rozszerzenia Allow-Control-Allow-Origin: * Rozszerzenie Chrome, aby obejść ten problem. Rozszerzenie doda niezbędne nagłówki HTTP dla CORS:

Access-Control-Allow-Origin: *
Access-Control-Allow-Methods: "GET, PUT, POST, DELETE, HEAD, OPTIONS"
Access-Control-Expose-Headers: <you can add values here>

Kod źródłowy został opublikowany na Github .

Pamiętaj, że rozszerzenie domyślnie filtruje wszystkie adresy URL. Może to spowodować uszkodzenie niektórych stron internetowych (na przykład: Dropbox). Zmieniłem to, aby filtrować tylko adresy URL hosta lokalnego z następującym filtrem adresów URL

*://localhost:*/*
Hanxue
źródło
14
Jeśli przeczytasz link do problemu @beau, zobaczysz, że Chrome 100% obsługuje żądania dotyczące różnych źródeł do i od hosta lokalnego. Problem został zamknięty w 2014 r., Ponieważ nie można go odtworzyć. Reszta szumu w tym wątku to ludzie ze źle skonfigurowanymi serwerami nie pochodzącymi (jak w przypadku oryginalnego pytania tutaj).
Molomby,
1
Dla mnie działał jak urok na chromie
Aakash Sahai,
3
To rozszerzenie nie działa, Access-Control-Allow-Credentials: trueponieważ ustawia Access-Control-Allow-Originje *i ma truei *jest zablokowane przez przeglądarki. Jeśli używasz poświadczeń true, musisz użyć źródła innego niż symbol wieloznaczny. Polecam Moesif Origins i CORS Changer Extension, który pozwala zmieniać nagłówki w dowolny sposób.
Samuel
Może robię coś złego, ale wydaje się, że to rozszerzenie już nie działa.
James Parker
19

Prawdziwy problem polega na tym, że jeśli ustawimy -Allow-dla wszystkich żądań ( OPTIONSi POST), Chrome je anuluje. Poniższy kod działa dla mnie z POSTLocalHost z Chrome

<?php
if (isset($_SERVER['HTTP_ORIGIN'])) {
    //header("Access-Control-Allow-Origin: {$_SERVER['HTTP_ORIGIN']}");
    header("Access-Control-Allow-Origin: *");
    header('Access-Control-Allow-Credentials: true');    
    header("Access-Control-Allow-Methods: GET, POST, OPTIONS"); 
}   
if ($_SERVER['REQUEST_METHOD'] == 'OPTIONS') {
    if (isset($_SERVER['HTTP_ACCESS_CONTROL_REQUEST_METHOD']))
        header("Access-Control-Allow-Methods: GET, POST, OPTIONS");         
    if (isset($_SERVER['HTTP_ACCESS_CONTROL_REQUEST_HEADERS']))
        header("Access-Control-Allow-Headers:{$_SERVER['HTTP_ACCESS_CONTROL_REQUEST_HEADERS']}");

    exit(0);
} 
?>
greensuisse
źródło
15
OP używa nginx / node.js. Nie PHP
code_monk
4

Chrome będzie dobrze wysyłać żądania do CORS z localhostpochodzenia. To nie jest problem z Chrome.

Powodem, dla którego nie można załadować, http://stackoverflow.comjest to, że Access-Control-Allow-Originnagłówki nie zezwalały na Twoje localhostpochodzenie.

Ćwiek
źródło
2

Szybka i brudna poprawka rozszerzenia Chrome:

Moesif Orign & CORS Changer

Chrome obsługuje jednak żądania dotyczące różnych źródeł z hosta lokalnego. Pamiętaj, aby dodać nagłówek Access-Control-Allow-Origindla localhost.

kaleazy
źródło
dodałem to rozszerzenie do mojej Opery, a teraz jest już gotowe. nigdy nie wiem, kiedy jest włączony i wyłączony, więc używam Firefoxa do pracy. i opera rozwoju. garnitur Google go nie lubi, a inne rzeczy też nie.
Maddocks,
1

Żadne z rozszerzeń nie działało dla mnie, więc zainstalowałem prosty lokalny serwer proxy. W moim przypadku https://www.npmjs.com/package/local-cors-proxy Jest to konfiguracja 2-minutowa:

(z ich strony)

npm install -g local-cors-proxy

Punkt końcowy interfejsu API, który chcemy zażądać, mający problemy z CORS: https://www.yourdomain.ie/movies/list

Uruchom serwer proxy: lcp --proxyUrl https://www.yourdomain.ie

Następnie w kodzie klienta nowy punkt końcowy interfejsu API: http://localhost:8010/proxy/movies/list

Dla mnie zadziałało: twoja aplikacja wywołuje proxy, który dzwoni do serwera. Zero problemów CORS.

Daniel p
źródło
0

Postanowiłem nie dotykać nagłówków i zamiast tego przekierowywać po stronie serwera, a to działa jak urok.

Poniższy przykład dotyczy bieżącej wersji Angulara (obecnie 9) i prawdopodobnie każdego innego frameworka używającego webpacks DevServer. Ale myślę, że ta sama zasada będzie działać na innych backendach.

Dlatego używam następującej konfiguracji w pliku proxy.conf.json :

{
  "/api": {
    "target": "http://localhost:3000",
    "pathRewrite": {"^/api" : ""},
   "secure": false
 }
}

W przypadku Angulara obsługuję w tej konfiguracji:

$ ng serve -o --proxy-config=proxy.conf.json

Wolę używać proxy w poleceniu służyć, ale można również umieścić tę konfigurację do angular.json tak:

"architect": {
  "serve": {
    "builder": "@angular-devkit/build-angular:dev-server",
    "options": {
      "browserTarget": "your-application-name:build",
      "proxyConfig": "src/proxy.conf.json"
    },

Zobacz też:

https://www.techiediaries.com/fix-cors-with-angular-cli-proxy-configuration/

https://webpack.js.org/configuration/dev-server/#devserverproxy

Juri Sinitson
źródło