Brak „Kontroli dostępu - Zezwalaj na pochodzenie” - Problem z węzłem / portem Apache


260

utworzyłem mały interfejs API za pomocą Node / Express i próbuję pobrać dane za pomocą Angularjs, ale ponieważ moja strona HTML działa pod apache na localhost: 8888, a API węzła nasłuchuje na porcie 3000, otrzymuję brak kontroli dostępu Allow-Origin ”. Próbowałem używać node-http-proxyApache i Vhosts, ale nie odniosłem dużego sukcesu, zobacz pełny błąd i kod poniżej.

XMLHttpRequest nie może załadować localhost: 3000. Żądany zasób nie zawiera nagłówka „Access-Control-Allow-Origin”. Dlatego „localhost: 8888” pochodzenia nie ma dostępu. ”

// Api Using Node/Express    
var express = require('express');
var app = express();
var contractors = [
    {   
     "id": "1", 
        "name": "Joe Blogg",
        "Weeks": 3,
        "Photo": "1.png"
    }
];

app.use(express.bodyParser());

app.get('/', function(req, res) {
  res.json(contractors);
});
app.listen(process.env.PORT || 3000);
console.log('Server is running on Port 3000')

Kod kątowy

angular.module('contractorsApp', [])
.controller('ContractorsCtrl', function($scope, $http,$routeParams) {

   $http.get('localhost:3000').then(function(response) {
       var data = response.data;
       $scope.contractors = data;
   })

HTML

<body ng-app="contractorsApp">
    <div ng-controller="ContractorsCtrl"> 
        <ul>
            <li ng-repeat="person in contractors">{{person.name}}</li>
        </ul>
    </div>
</body>

Odpowiedzi:


621

Spróbuj dodać następujące oprogramowanie pośrednie do aplikacji NodeJS / Express (dla Twojej wygody dodałem kilka komentarzy):

// Add headers
app.use(function (req, res, next) {

    // Website you wish to allow to connect
    res.setHeader('Access-Control-Allow-Origin', 'http://localhost:8888');

    // Request methods you wish to allow
    res.setHeader('Access-Control-Allow-Methods', 'GET, POST, OPTIONS, PUT, PATCH, DELETE');

    // Request headers you wish to allow
    res.setHeader('Access-Control-Allow-Headers', 'X-Requested-With,content-type');

    // Set to true if you need the website to include cookies in the requests sent
    // to the API (e.g. in case you use sessions)
    res.setHeader('Access-Control-Allow-Credentials', true);

    // Pass to next layer of middleware
    next();
});

Mam nadzieję, że to pomaga!


2
Czy możesz pomóc dokładnie określić, dokąd to idzie? Mam następujący kod na swoim serwerze. Czy zaraz potem? var app = wymagają („ekspresowe”) (), serwer = wymagają („http”). createServer (aplikacja), io = wymagają („socket.io”). nasłuchuje (serwer), żądanie = wymaga („żądanie”) , url = wymagają („url”); server.listen (6969); // czy to idzie tutaj? na nowej linii?
— Art Geigel

1
@jvandemo czy muszę zmienić app.get ('/', function (req, res) na ... function (req, res, next)?
— Sangram Singh

10
Jesteś teraz moją ulubioną osobą. Dziękuję Ci. Czy możemy dodać notatkę, że ten kod musi się zdarzyć, zanim zostaną zdefiniowane trasy dla noobów takich jak ja?
— gegillam

1
Jak sprawić, by działało to podczas korzystania z modułu żądania?
— Rohit Tigga

2
W moim przypadku nie zadziałało. Nadal pojawia się błąd: „Odpowiedź na żądanie inspekcji wstępnej nie przechodzi kontroli kontroli dostępu: Żądany zasób nie zawiera nagłówka„ Kontrola dostępu - Zezwalaj na pochodzenie ”. Z tego powodu pochodzenie„ abc.xyz.net:212 ”jest niedozwolone dostęp. Odpowiedź miała kod statusu HTTP 500. ”
— user1451111,

96

Zaakceptowana odpowiedź jest w porządku, jeśli wolisz coś krótszego, możesz użyć wtyczki o nazwie cors dostępnej dla Express.js

Jest prosty w użyciu, w tym konkretnym przypadku:

var cors = require('cors');

// use it before all route definitions
app.use(cors({origin: 'http://localhost:8888'}));

3
Musiałem użyć, {origin: 'null'}aby to działało ... Najwyraźniej moja przeglądarka wysyła nulljako źródło?
— Ricardo Cruz,

2
Po co wymyślać koło ponownie. Zawsze opowiadam się za pakietem rozwiązań w porównaniu do fragmentu kodu
— Pierre

słodka mała biblioteka, która poradziła sobie z moim przypadkiem użycia różnych metod z różnych źródeł całkiem ładnie ... i mniej zmęczenia kodu dla następnego faceta, który na to spojrzy.
— Kyle Baker

6
Dzięki, app.use(cors({origin: '*'}));pracował dla mnie, jak na Ena-Cors .
— danialk

2
Sugeruję zajrzeć na stronę npm cors, aby lepiej z niej skorzystać. Wyjaśniło mi to bardzo jasno =).
— 13013SwagR

30

Innym sposobem jest dodanie nagłówków do trasy:

router.get('/', function(req, res) {
    res.setHeader('Access-Control-Allow-Origin', '*');
    res.setHeader('Access-Control-Allow-Methods', 'GET, POST, OPTIONS, PUT, PATCH, DELETE'); // If needed
    res.setHeader('Access-Control-Allow-Headers', 'X-Requested-With,content-type'); // If needed
    res.setHeader('Access-Control-Allow-Credentials', true); // If needed

    res.send('cors problem fixed:)');
});

8
)buźki pomylił mnie
— diEcho

17

Top odpowiedź działało w porządku dla mnie, chyba że muszę whitelist więcej niż jedną domenę.

Również najlepsza odpowiedź cierpi z tego powodu OPTIONS żądanie nie jest obsługiwane przez oprogramowanie pośrednie i nie otrzymujesz go automatycznie.

Domeny z białej listy przechowuję jak allowed_originsw konfiguracji Express i od tego czasu umieszczam poprawną domenę zgodnie z originnagłówkiemAccess-Control-Allow-Origin nie pozwala na określenie więcej niż jednej domeny.

Oto, z czym skończyłem:

var _ = require('underscore');

function allowCrossDomain(req, res, next) {
  res.setHeader('Access-Control-Allow-Methods', 'GET, POST, OPTIONS');

  var origin = req.headers.origin;
  if (_.contains(app.get('allowed_origins'), origin)) {
    res.setHeader('Access-Control-Allow-Origin', origin);
  }

  if (req.method === 'OPTIONS') {
    res.send(200);
  } else {
    next();
  }
}

app.configure(function () {
  app.use(express.logger());
  app.use(express.bodyParser());
  app.use(allowCrossDomain);
});

Czy to to samo „if (app.get („ dozwolone źródła ”). IndexOf (pochodzenie)! == - 1)?”?
— Rune Jeppesen,

13

Kod odpowiedzi pozwala tylko na localhost: 8888. Tego kodu nie można wdrożyć w produkcji ani pod inną nazwą serwera i portu.

Aby działał dla wszystkich źródeł, użyj tego zamiast tego:

// Add headers
app.use(function (req, res, next) {

    // Website you wish to allow to connect
    res.setHeader('Access-Control-Allow-Origin', '*');

    // Request methods you wish to allow
    res.setHeader('Access-Control-Allow-Methods', 'GET, POST, OPTIONS, PUT, PATCH, DELETE');

    // Request headers you wish to allow
    res.setHeader('Access-Control-Allow-Headers', 'X-Requested-With,content-type');

    // Set to true if you need the website to include cookies in the requests sent
    // to the API (e.g. in case you use sessions)
    res.setHeader('Access-Control-Allow-Credentials', true);

    // Pass to next layer of middleware
    next();
});

2
To mi nie działa! „* nie jest prawidłowym źródłem”. Wygląda na to, że * znak nie jest rozpoznawany jako symbol wieloznaczny.
— Francesco

Mi to pasuje. tzn. używając symbolu wieloznacznego „*”. działa zarówno na Chrome, jak i na Safari.
— AnBisw

Dzięki;) Działa dobrze
— Mauro

9

Zainstaluj zależność cors w swoim projekcie:

npm i --save cors

Dodaj do pliku konfiguracyjnego serwera:

var cors = require('cors');
app.use(cors());

Działa dla mnie z wersją cors 2.8.4.


"cors": "^2.8.5", "express": "^4.16.3",działa dobrze tylko z sugerowaną linią @monikaja. Dzięki!
— RamiroIsBack

Umożliwia to wszystkim źródłom / domenom dostęp do aplikacji, czego zwykle nie chcesz robić. Zamiast tego podaj tylko dozwolone domeny.
— Lacho Tomov

7

To zadziałało dla mnie.

app.get('/', function (req, res) {

    res.header("Access-Control-Allow-Origin", "*");
    res.send('hello world')
})

Możesz zmienić * w zależności od potrzeb. Mam nadzieję, że to może pomóc.


7

Cześć, dzieje się tak, gdy frontend i backend działają na różnych portach. Przeglądarka blokuje odpowiedzi z zaplecza z powodu braku nagłówków CORS. Rozwiązaniem jest dodanie nagłówków CORS do żądania zaplecza. Najprostszym sposobem jest użycie pakietu cors npm.

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

Umożliwi to nagłówki CORS we wszystkich twoich żądaniach. Więcej informacji można znaleźć w dokumentacji corsa

https://www.npmjs.com/package/cors


3
app.all('*', function(req, res,next) {
    /**
     * Response settings
     * @type {Object}
     */
    var responseSettings = {
        "AccessControlAllowOrigin": req.headers.origin,
        "AccessControlAllowHeaders": "Content-Type,X-CSRF-Token, X-Requested-With, Accept, Accept-Version, Content-Length, Content-MD5,  Date, X-Api-Version, X-File-Name",
        "AccessControlAllowMethods": "POST, GET, PUT, DELETE, OPTIONS",
        "AccessControlAllowCredentials": true
    };

    /**
     * Headers
     */
    res.header("Access-Control-Allow-Credentials", responseSettings.AccessControlAllowCredentials);
    res.header("Access-Control-Allow-Origin",  responseSettings.AccessControlAllowOrigin);
    res.header("Access-Control-Allow-Headers", (req.headers['access-control-request-headers']) ? req.headers['access-control-request-headers'] : "x-requested-with");
    res.header("Access-Control-Allow-Methods", (req.headers['access-control-request-method']) ? req.headers['access-control-request-method'] : responseSettings.AccessControlAllowMethods);

    if ('OPTIONS' == req.method) {
        res.send(200);
    }
    else {
        next();
    }


});

2

Dodaj następujący kod do app.js NODEJ Restful api, aby uniknąć błędu „Access-Control-Allow-Origin” w kątowniku 6 lub innym frameworku

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

var cors = require('cors');
var bodyParser = require('body-parser');

//enables cors
app.use(cors({
  'allowedHeaders': ['sessionId', 'Content-Type'],
  'exposedHeaders': ['sessionId'],
  'origin': '*',
  'methods': 'GET,HEAD,PUT,PATCH,POST,DELETE',
  'preflightContinue': false
}));

1

Możesz użyć „$ http.jsonp”

LUB

Poniżej znajduje się obejście dotyczące Chrome do testowania lokalnego

Musisz otworzyć Chrome za pomocą następującego polecenia. (Naciśnij okno + R)

Chrome.exe --allow-file-access-from-files

Uwaga: Twój chrom nie może być otwarty. Po uruchomieniu tego polecenia chrome otworzy się automatycznie.

Jeśli wpisujesz to polecenie w wierszu polecenia, wybierz katalog instalacyjny chrome, a następnie użyj tego polecenia.

Poniżej kod skryptu dla otwartego chrome w MAC z „--allow-file-access-from-files”

set chromePath to POSIX path of "/Applications/Google Chrome.app/Contents/MacOS/Google Chrome" 
set switch to " --allow-file-access-from-files"
do shell script (quoted form of chromePath) & switch & " > /dev/null 2>&1 &"

drugie opcje

Możesz po prostu użyć open (1), aby dodać flagi: open -a „Google Chrome” --args --allow-file-access-from-files


Co powiesz na MAC? Chrome.exe --allow-file-access-from-files
— user1336103

/ Aplikacje / Google \ Chrome.app/Contents/MacOS/Google \ Chrome --allow-file-access-from-files udaje się otworzyć Chrome, ale komunikat nadal pokazuje „XMLHttpRequest nie może załadować localhost: 3000. Pochodzenie localhost: 8888 to niedozwolone przez Access-Control-Allow-Origin. ”
— 1336103,

+1 Mogę potwierdzić, że działa z opcją Mac za pomocą „open”. Moja sprawa jest nieco inna, ponieważ po prostu testuję całkowicie pobraną witrynę, która ma dostęp do niektórych lokalnych plików JSON.
— gąbka

0

/**
 * Allow cross origin to access our /public directory from any site.
 * Make sure this header option is defined before defining of static path to /public directory
 */
expressApp.use('/public',function(req, res, next) {
    res.setHeader("Access-Control-Allow-Origin", "*");
    // Request headers you wish to allow
    res.setHeader("Access-Control-Allow-Headers", "Origin, X-Requested-With, Content-Type, Accept");
    // Set to true if you need the website to include cookies in the requests sent
    res.setHeader('Access-Control-Allow-Credentials', true);
    // Pass to next layer of middleware
    next();
});


/**
 * Server is about set up. Now track for css/js/images request from the 
 * browser directly. Send static resources from "./public" directory. 
 */
expressApp.use('/public', express.static(path.join(__dirname, 'public')));
If you want to set Access-Control-Allow-Origin to a specific static directory you can set the following.

Korzystając z naszej strony potwierdzasz, że przeczytałeś(-aś) i rozumiesz nasze zasady używania plików cookie i zasady ochrony prywatności.
Licensed under cc by-sa 3.0 with attribution required.