Pochodzenie <origin> nie jest dozwolone przez Access-Control-Allow-Origin

184
XMLHttpRequest cannot load http://localhost:8080/api/test. Origin http://localhost:3000 is not allowed by Access-Control-Allow-Origin. 

Czytałem o zapytaniach AJAX między domenami i rozumiem podstawowy problem z bezpieczeństwem. W moim przypadku 2 serwery działają lokalnie i lubią włączać żądania międzydomenowe podczas testowania.

localhost:8080 - Google Appengine dev server
localhost:3000 - Node.js server

Wystawiam żądanie AJAX do, localhost:8080 - GAE servergdy moja strona jest ładowana z serwera węzła. Co jest najłatwiejsze i najbezpieczniejsze (nie chcę uruchamiać chrome z disable-web-securityopcją). Jeśli muszę zmienić 'Content-Type', czy powinienem to zrobić na serwerze węzła? W jaki sposób?

bsr
źródło
Szybsze rozwiązanie można znaleźć tutaj: stackoverflow.com/a/21622564/4455570
Gabriel Wamunyu

Odpowiedzi:

195

Ponieważ działają na różnych portach, są to różne JavaScript origin. Nie ma znaczenia, że ​​są na tej samej maszynie / nazwie hosta.

Musisz włączyć CORS na serwerze (localhost: 8080). Sprawdź tę witrynę: http://enable-cors.org/

Wszystko, co musisz zrobić, to dodać nagłówek HTTP do serwera:

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

Lub dla uproszczenia:

Access-Control-Allow-Origin: *

Nie należy używać znaku „*”, jeśli serwer próbuje ustawić plik cookie, a Ty używasz withCredentials = true

odpowiadając na żądanie poświadczone, serwer musi określić domenę i nie może używać symboli wieloznacznych.

Możesz przeczytać więcej o tym withCredentialstutaj

Rocket Hazmat
źródło
jeśli chcemy dodać ten nagłówek do kodu HTML, co powinniśmy z tym zrobić?
Azam Alvi
1
Nie sądziłem, że ten port jest konieczny, ale jeśli używasz niestandardowego portu, takiego jak 3000, musisz uwzględnić go w zasadach CORS.
Michael Connor
4
Dzięki za tę odpowiedź. Chcę tylko podkreślić implikacje bezpieczeństwa wynikające z użycia „*” jako wartości tutaj. To pozwala wszystkim źródłom: developer.mozilla.org/en-US/docs/Web/HTTP/Headers/ ... Wygląda na to, że pierwszy przykład byłby najlepszy pod względem najmniejszego dostępu. Szczegółowe informacje o tym, jak to zrobić z wieloma domenami, znajdziesz tutaj: stackoverflow.com/a/1850482/1566623
Christopher Kuttruff
14
Dla jasności, kiedy mówi się, że trzeba „dodać nagłówek HTTP do serwera”, oznacza to, że dany Access-Control-Allow-Originnagłówek musi być nagłówkiem dodanym do odpowiedzi HTTP wysyłanych przez serwer. Ten nagłówek musi być częścią odpowiedzi serwera, nie musi być częścią żądania klienta . W szczególności dzieje się, zanim klient wyśle ​​żądane żądanie , przeglądarka wysyła OPTIONSżądanie przed nim, a jeśli odpowiedź serwera na to OPTIONSżądanie nie zawiera nagłówka, przeglądarka nie wyśle ​​żądanego żądania.
AjaxLeung
1
Ważne jest, aby przeczytać odpowiednie wskazówki dotyczące serwerów zaplecza na stronie enable-cors.org.
Karlth
69

Jeśli potrzebujesz szybkiego obejścia w Chrome dla żądań Ajax, ta wtyczka Chrome automatycznie umożliwia dostęp do dowolnej witryny z dowolnego źródła, dodając odpowiedni nagłówek odpowiedzi

Rozszerzenie Chrome Allow-Control-Allow-Origin: *

Billy Baker
źródło
6
Nie wiem, dlaczego nie dostajesz więcej pozytywnych głosów. Jest to najmniej uciążliwe dla programowania na hoście lokalnym z Chrome.
David Betz
zdecydowanie się zgadzam. Łatwe do włączenia dla deweloperów localhost na zdalnym serwerze bez konieczności zmiany konfiguracji zdalnego serwera.
Jens Wegar
@DavidBetz: biorąc pod uwagę, że zweryfikujesz rozszerzenie i ufasz mu, oczywiście;)
haylem
2
TO POWINNO BYĆ NAJLEPSZA ODPOWIEDŹ! Zwłaszcza jeśli chodzi o localhost.
Pan Benedict,
16
Gdyby to było dobre rozwiązanie, nie zostałby wynaleziony CORS. Zastosowanie tego nagłówka do dowolnego hosta wyłącza ochronę CORS i naraża cię na złośliwe skrypty, nie tylko twoje. Nie zdziw się, jeśli Twoje konto bankowe nagle się opróżni.
dolmen
54

Musisz włączyć CORS, aby rozwiązać ten problem

jeśli Twoja aplikacja została utworzona za pomocą prostego node.js.

ustaw go w nagłówkach odpowiedzi, takich jak

var http = require('http');

http.createServer(function (request, response) {
response.writeHead(200, {
    'Content-Type': 'text/plain',
    'Access-Control-Allow-Origin' : '*',
    'Access-Control-Allow-Methods': 'GET,PUT,POST,DELETE'
});
response.end('Hello World\n');
}).listen(3000);

jeśli Twoja aplikacja została utworzona w ramach ekspresowej platformy

użyj oprogramowania pośredniczącego CORS, takiego jak

var allowCrossDomain = function(req, res, next) {
    res.header('Access-Control-Allow-Origin', "*");
    res.header('Access-Control-Allow-Methods', 'GET,PUT,POST,DELETE');
    res.header('Access-Control-Allow-Headers', 'Content-Type');
    next();
}

i aplikuj przez

app.configure(function() {
    app.use(allowCrossDomain);
    //some other code
});    

Oto dwa linki referencyjne

  1. jak zezwolić-cors-in-express-nodejs
  2. nurkowanie w node-js-very-first-app # zobacz sekcję Ajax
mithunsatheesh
źródło
czy możesz określić, jak używać config.allowedDomains. powiedz w moim przypadku, jakie URI mam tam umieścić?
bsr,
@bsr: możesz użyć *lub, do specific domainktórego chcesz przyznać dostęp.
mithunsatheesh,
1
więc czy tylko ja otrzymuję app.configure()to nie błąd funkcji?
Pramesh Bajracharya
@PrameshBajrachaya Nie załączyłem „app.configure” part - only „app.use (allowCrossDomain)” i to zadziałało.
Giorgos Sfikas
8

Akceptuję odpowiedź @Rocket Hazmat, która prowadzi mnie do rozwiązania. Rzeczywiście musiałem ustawić nagłówek na serwerze GAE. Musiałem to ustawić

"Access-Control-Allow-Origin" -> "*"
"Access-Control-Allow-Headers" -> "Origin, X-Requested-With, Content-Type, Accept"

ustawienie "Access-Control-Allow-Origin" dawało tylko błąd

Request header field X-Requested-With is not allowed by Access-Control-Allow-Headers.

Ponadto, jeśli trzeba wysłać token uwierzytelniania, dodaj to również

"Access-Control-Allow-Credentials" -> "true"

Również u klienta ustawione withCredentials

powoduje to wysłanie 2 żądań do serwera, w tym jednego z OPTIONS. Plik cookie uwierzytelniający nie jest wysyłany wraz z nim, dlatego należy traktować uwierzytelnianie zewnętrzne.

bsr
źródło
7

W routerze.js po prostu dodaj kod przed wywołaniem metod get / post. U mnie działa bezbłędnie.

//Importing modules @Brahmmeswar
const express = require('express');
const router = express.Router();

const Contact = require('../models/contacts');

router.use(function(req, res, next) {
    res.header("Access-Control-Allow-Origin", "*");
    res.header("Access-Control-Allow-Headers", "Origin, X-Requested-With, Content-Type, Accept");
    next();
  });
Brahmmeswara Rao Palepu
źródło
5

Miałem problem podczas wywoływania zasobów pochodzących z innych źródeł przy użyciu AJAX z Chrome.

Użyłem node js i lokalnego serwera http do wdrożenia mojej aplikacji node js.

Otrzymałem odpowiedź o błędzie podczas uzyskiwania dostępu do zasobu między źródłami

Znalazłem na to jedno rozwiązanie,

1) Dodałem poniższy kod do mojego pliku app.js.

res.header("Access-Control-Allow-Origin", "*");
res.header("Access-Control-Allow-Headers", "X-Requested-With");

2) Na mojej stronie html o nazwie cross-origin resource using $.getJSON();

$.getJSON("http://localhost:3000/users", function (data) {
    alert("*******Success*********");
    var response=JSON.stringify(data);
    alert("success="+response);
    document.getElementById("employeeDetails").value=response;
});
Chaitanya
źródło
5

Jeśli korzystasz z usługi Express, możesz użyć oprogramowania pośredniego cors w następujący sposób:

var express = require('express')
var cors = require('cors')
var app = express()

app.use(cors())
Akalanka Weerasooriya
źródło
3

Dodaj to do swojego serwera NodeJS poniżej importu:

app.use(function(req, res, next) {
  res.header("Access-Control-Allow-Origin", "*");
  res.header("Access-Control-Allow-Headers", "Origin, X-Requested-With, Content-Type, Accept");
  next();
});
Ryan Cocuzzo
źródło
3

Jeśli po tym otrzymałeś 403, zredukuj filtry w konfiguracji tomcat WEB.XML do następującego:

<filter>
  <filter-name>CorsFilter</filter-name>
  <filter-class>org.apache.catalina.filters.CorsFilter</filter-class>
  <init-param>
    <param-name>cors.allowed.origins</param-name>
    <param-value>*</param-value>
  </init-param>
  <init-param>
    <param-name>cors.allowed.methods</param-name>
    <param-value>GET,POST,HEAD,OPTIONS,PUT</param-value>
  </init-param>
  <init-param>
    <param-name>cors.allowed.headers</param-name>
    <param-value>Content-Type,X-Requested-With,accept,Origin,Access-Control-Request-Method,Access-Control-Request-Headers</param-value>
  </init-param>
  <init-param>
    <param-name>cors.exposed.headers</param-name>
    <param-value>Access-Control-Allow-Origin,Access-Control-Allow-Credentials</param-value>
  </init-param>
</filter>
Farbod Aprin
źródło
2

W końcu dostałem odpowiedź na apache Tomcat8

Musisz edytować plik tomcat web.xml.

prawdopodobnie będzie w folderze webapps,

sudo gedit /opt/tomcat/webapps/your_directory/WEB-INF/web.xml

znajdź go i edytuj

<web-app>


<filter>
  <filter-name>CorsFilter</filter-name>
  <filter-class>org.apache.catalina.filters.CorsFilter</filter-class>
  <init-param>
    <param-name>cors.allowed.origins</param-name>
    <param-value>*</param-value>
  </init-param>
  <init-param>
    <param-name>cors.allowed.methods</param-name>
    <param-value>GET,POST,HEAD,OPTIONS,PUT</param-value>
  </init-param>
  <init-param>
    <param-name>cors.allowed.headers</param-name>
    <param-value>Content-Type,X-Requested-With,accept,Origin,Access-Control-Request-Method,Access-Control-Request-Headers</param-value>
  </init-param>
  <init-param>
    <param-name>cors.exposed.headers</param-name>
    <param-value>Access-Control-Allow-Origin,Access-Control-Allow-Credentials</param-value>
  </init-param>
  <init-param>
    <param-name>cors.support.credentials</param-name>
    <param-value>true</param-value>
  </init-param>
  <init-param>
    <param-name>cors.preflight.maxage</param-name>
    <param-value>10</param-value>
  </init-param>
</filter>


<filter-mapping>
  <filter-name>CorsFilter</filter-name>
  <url-pattern>/*</url-pattern>
</filter-mapping>



</web-app>

Umożliwi to dostęp-kontrolę-zezwolenie-pochodzenia wszystkim hostom. Jeśli chcesz zmienić go ze wszystkich hostów na tylko swój host, możesz edytować plik

<param-name>cors.allowed.origins</param-name>
<param-value>http://localhost:3000</param-value>

powyższy kod od * do adresu http: // your_public_IP lub http://www.example.com

możesz odwołać się tutaj dokumentacji filtra Tomcat

Dzięki

Shinto Joseph
źródło
1

Cześć To jest sposób na rozwiązanie problemu CORS w węźle Po prostu dodaj te linie po stronie "api" serwera w Node.js (lub jakimkolwiek pliku serwera), zanim to upewnij się, że zainstalowałeś "cors"

    const express = require('express');
    const app = express();
    app.use(express.json());
    var cors = require('cors');
    app.use(cors());
Saad Abbasi
źródło
0

użyj typu dataType: „jsonp”, działa dla mnie.

   async function get_ajax_data(){

       var _reprojected_lat_lng = await $.ajax({

                                type: 'GET',

                                dataType: 'jsonp',

                                data: {},

                                url: _reprojection_url,

                                error: function (jqXHR, textStatus, errorThrown) {

                                    console.log(jqXHR)

                                },

                                success: function (data) {

                                    console.log(data);



                                    // note: data is already json type, you just specify dataType: jsonp

                                    return data;

                                }

                            });





 } // function               
hoogw
źródło
0

W przypadku PHP użyj tego do ustawienia nagłówków.

header("Access-Control-Allow-Origin: *");
header("Access-Control-Allow-Methods: PUT, GET, POST");
header("Access-Control-Allow-Headers: Origin, X-Requested-With, Content-Type, Accept");
Hamza Waleed
źródło
0
router.use(function(req, res, next) {
res.header("Access-Control-Allow-Origin", "*");
res.header("Access-Control-Allow-Methods", "*");
res.header("Access-Control-Allow-Headers", "*");
next();});

dodaj to do swoich tras, do których dzwonisz z front-endu. Np. Jeśli wywołujesz http: // localhost: 3000 / users / register , musisz dodać ten fragment kodu do pliku .js zaplecza, który tworzy ta trasa.

Sujeewa K. Abeysinghe
źródło
0

Jeśli ktoś szuka rozwiązania, jeśli korzystasz z ekspresu, to szybkie rozwiązanie.

const express = require('express')
const cors = require('cors')
const app = express()

1) zainstaluj przewody za pomocą npm npm install cors --save

2) zaimportuj [wymagaj] const cors = require('cors')

3) używać go jako oprogramowania pośredniego app.use(cors())

aby uzyskać szczegółowe informacje, wstaw i zastosowanie cors . To jest to, mam nadzieję, że działa.

Badri Paudel
źródło