Die Antwort auf die Preflight-Anforderung besteht die Zugriffskontrollprüfung nicht

457

Ich erhalte diesen Fehler, wenn ngResource zum Aufrufen einer REST-API in Amazon Web Services verwendet wird:

XMLHttpRequest kann http://server.apiurl.com:8000/s/login?login=facebook nicht laden . Die Antwort auf die Preflight-Anforderung besteht die Zugriffssteuerungsprüfung nicht: In der angeforderten Ressource ist kein Header 'Access-Control-Allow-Origin' vorhanden. Origin ' http: // localhost ' ist daher kein Zugriff gestattet. Fehler 405

Bedienung:

socialMarkt.factory('loginService', ['$resource', function($resource){    
    var apiAddress = "http://server.apiurl.com:8000/s/login/";
    return $resource(apiAddress, { login:"facebook", access_token: "@access_token" ,facebook_id: "@facebook_id" }, {
                getUser: {method:'POST'}
            });
}]);

Regler:

[...]
loginService.getUser(JSON.stringify(fbObj)),
                function(data){
                    console.log(data);
                },
                function(result) {
                    console.error('Error', result.status);
                }
[...]

Ich verwende Chrome und weiß nicht, was ich sonst tun soll, um dieses Problem zu beheben. Ich habe den Server sogar so konfiguriert, dass er Header vom Ursprung akzeptiert localhost.

Andre Mendes
quelle
verwirrt: hast du "den server konfiguriert" oder ist das "eine rest api auf amazon web service"?
Dandavis
3
Sie haben offensichtlich nicht genug getan, um CORS auf der Serverseite zu aktivieren. Post Probe der Antwort Header
charlietfl
4
In jedem Fall sind Ihre Abstimmungen falsch. Er hostet seine Dateien auf seinem lokalen Computer. Es spielt keine Rolle, welche Art von Conf er am Backend macht. Angular erlaubt diesen Vorflug nicht.
E. Maggini
3
Vielen Dank für die Kommentare, es hat funktioniert, als ich den Browser auf Sicherheit eingestellt habe
Andre Mendes
1
@Andre Aber das Ausschalten der Sicherheit ist nur eine hässliche Problemumgehung, bei der Sie Kompromisse bei der Sicherheit eingehen und Ihr Problem nicht lösen ...
Shivi

Antworten:

240

Sie haben Probleme mit CORS.

Es gibt verschiedene Möglichkeiten, dies zu beheben / zu umgehen.

  1. Schalten Sie CORS aus. Zum Beispiel: Wie man Cors in Chrom ausschaltet
  2. Verwenden Sie ein Plugin für Ihren Browser
  3. Verwenden Sie einen Proxy wie Nginx. Beispiel für die Einrichtung
  4. Führen Sie die erforderlichen Einstellungen für Ihren Server durch. Dies ist eher ein Faktor des Webservers, den Sie auf Ihre EC2-Instanz geladen haben (vorausgesetzt, Sie meinen dies mit "Amazon-Webdienst"). Informationen zu Ihrem spezifischen Server finden Sie auf der Website zum Aktivieren von CORS.

Ausführlicher ist, dass Sie versuchen, von localhost aus auf api.serverurl.com zuzugreifen. Dies ist die genaue Definition der domänenübergreifenden Anforderung.

Wenn Sie es entweder ausschalten, um Ihre Arbeit zu erledigen (OK, stellen Sie eine schlechte Sicherheit für Sie bereit, wenn Sie andere Websites besuchen und nur die Dose in die Knie zwingen), können Sie einen Proxy verwenden, der Ihren Browser glauben lässt, dass alle Anfragen vom lokalen Host kommen, wenn Sie haben wirklich einen lokalen Server, der dann den Remote-Server aufruft.

Daher wird api.serverurl.com möglicherweise zu localhost: 8000 / api und Ihr lokaler Nginx oder ein anderer Proxy wird an das richtige Ziel gesendet.


Jetzt auf vielfachen Wunsch 100% mehr CORS-Infos .... gleicher toller Geschmack!


Und für die Downvoter ... die Umgehung von CORS ist genau das, was für diejenigen gezeigt wird, die einfach das Frontend lernen. https://codecraft.tv/courses/angular/http/http-with-promises/

E. Maggini
quelle
776
ließ das Offensichtliche der korrekten Implementierung von CORS aus
charlietfl
40
Es ist leicht, abzustimmen. Es ist weniger einfach, das Risiko selbst einzugehen, mein Freund. Und all dies funktioniert genau in einer Entwicklungsumgebung.
E. Maggini
3
Es hat tatsächlich funktioniert. Ich habe das Flag hinzugefügt, um die Web-Sicherheit zu deaktivieren. Denn die Entwicklung ist in Ordnung.
Andre Mendes
15
@charlietfl Wie?
GreenAsJade
3
Danke, dass du meinen Tag gerettet hast. Nur erste Option verwendet: C: \ Programme (x86) \ Google \ Chrome \ Application> chrome.exe --user-data-dir = "C: \ Chrome dev session" --disable-web-security. Von: stackoverflow.com/questions/3102819/…
Harsimer
169

Mein "API-Server" ist eine PHP-Anwendung. Um dieses Problem zu lösen, habe ich die folgende Lösung gefunden:

Platzieren Sie die Zeilen in index.php

header('Access-Control-Allow-Origin: *');
header('Access-Control-Allow-Methods: GET, POST, PATCH, PUT, DELETE, OPTIONS');
header('Access-Control-Allow-Headers: Origin, Content-Type, X-Auth-Token');
Windschatten
quelle
3
Ich stimme zu, dies ist besser als die akzeptierte Antwort. Seien Sie jedoch vorsichtig, wenn Sie diese Zeilen kopieren. Achten Sie darauf, die Methoden und den Ursprung zu ändern.
Amir Savand
11
Wo soll es in ein Angular 6-Projekt eingefügt werden?
Whatthefish
@CodyBugstein und was der Fisch vor jeder Ausgabe stellte
Garet Claborn
Meine Client-App funktionierte nicht mehr, als ich einen Header hinzufügte, der nur von einigen Servern benötigt wird. Wenn die Anforderung benutzerdefinierte Header enthält, müssen diese in aufgelistet werden Access-Control-Allow-Headers.
z0r
47

In der AspNetCore-Web-API wurde dieses Problem behoben, indem "Microsoft.AspNetCore.Cors" (Version 1.1.1) hinzugefügt und die folgenden Änderungen in Startup.cs hinzugefügt wurden.

public void ConfigureServices(IServiceCollection services)
{ 
    services.AddCors(options =>
    {
          options.AddPolicy("AllowAllHeaders",
                builder =>
            {
                    builder.AllowAnyOrigin()
                           .AllowAnyHeader()
                           .AllowAnyMethod();
                });
    });
    .
    .
    .
}

und

public void Configure(IApplicationBuilder app, IHostingEnvironment env, ILoggerFactory loggerFactory)
{


    // Shows UseCors with named policy.
    app.UseCors("AllowAllHeaders");
    .
    .
    .
}

und setzen [EnableCors("AllowAllHeaders")] des Controllers.

Rajkumar Peter
quelle
18
Dies ist eine gute Antwort, wenn Sie Cross-Site-Scripting-Schwachstellen einbauen möchten! Bitte mach das niemals! Geben Sie Ihre Domänen an, auf die Sie zugreifen können, um Sicherheitsprobleme zu vermeiden. CORS ist aus einem bestimmten Grund da.
Paqogomez
2
Nur um es @paqogomez in Ihrer ConfigureServices-Methode klarer zu machen: services.AddCors (options => {options.AddPolicy ("AllowSpecificOrigin", builder => {builder.WithOrigins (" localhost" ) .AllowAnyOrigin () .AllowAnyHeader (). AllowAnyMethod ();});}); und in Ihrer Configure-Methode: app.UseCors ("AllowSpecificOrigin");
Francisco Tena
28

Es gibt einige Einschränkungen, wenn es um CORS geht. Erstens erlaubt es keine Platzhalter, *aber halte mich nicht an diesem fest. Ich habe ihn irgendwo gelesen und kann den Artikel jetzt nicht finden.

Wenn Sie Anforderungen von einer anderen Domäne stellen, müssen Sie die zulässigen Ursprungsheader hinzufügen.

 Access-Control-Allow-Origin: www.other.com 

Wenn Sie Anforderungen stellen, die sich auf Serverressourcen wie POST / PUT / PATCH auswirken, und wenn sich der MIME-Typ von dem folgenden application/x-www-form-urlencodedunterscheidet multipart/form-data, oder text/plainder Browser automatisch eine OPTIONS-Anforderung vor dem Flug sendet, um beim Server zu prüfen, ob dies zulässig ist .

Ihre API / Ihr Server muss diese OPTIONS-Anforderungen entsprechend behandeln. Sie müssen mit dem entsprechenden access control headersund dem http-Antwortstatuscode antworten 200.

Die Überschriften sollten ungefähr so ​​sein, passen Sie sie an Ihre Bedürfnisse an:

   Access-Control-Allow-Methods: GET, POST, PUT, PATCH, POST, DELETE, OPTIONS
   Access-Control-Allow-Headers: Content-Type
   Access-Control-Max-Age: 86400

Der Max-Age-Header ist wichtig, in meinem Fall würde er ohne ihn nicht funktionieren. Ich denke, der Browser benötigt die Informationen darüber, wie lange die "Zugriffsrechte" gültig sind.

Wenn Sie z. B. eine POSTAnfrage mit application/jsonMIME aus einer anderen Domain stellen, müssen Sie außerdem den zuvor erwähnten Header zum Zulassen des Ursprungs hinzufügen, damit dies folgendermaßen aussieht:

   Access-Control-Allow-Origin: www.other.com 
   Access-Control-Allow-Methods: GET, POST, PUT, PATCH, POST, DELETE, OPTIONS
   Access-Control-Allow-Headers: Content-Type
   Access-Control-Max-Age: 86400

Wenn der Vorflug erfolgreich ist und alle erforderlichen Informationen erhält, wird Ihre eigentliche Anfrage gestellt.

Im Allgemeinen Access-Controlsollte in der Antwort angegeben werden , welche Header in der Erst- oder Vorfluganforderung angefordert werden, damit sie funktionieren.

Es gibt ein gutes Beispiel in den MDN-Dokumenten hier unter diesem Link , und Sie sollten auch diesen SO-Beitrag lesen

Sasa Blagojevic
quelle
1
Hier ist der Mozilla-Artikel, in dem es darum geht, wie Sie keinen Platzhalter für die Herkunft von Cors verwenden können: Link Dies gilt anscheinend nur für die Verwendung von Anmeldeinformationen (wenn ich das richtig verstehe)
Helzgate
Ich verwende einen Platzhalter und sende ein Inhaber-Token, um die Anfrage zu autorisieren. Es funktioniert einwandfrei. Ich bin mir also nicht sicher, auf was sich der oben angegebene Link in Bezug auf Anmeldeinformationen bezieht. Mein Problem war, dass ich beim Erstellen meiner CORS-Richtlinie in .Net Core nichts hinzugefügt habe .AllowCredentials(). Nach dem Hinzufügen hat .AllowCredentials()alles funktioniert.
Helzgate
15

JavaScript XMLHttpRequest und Fetch folgen der Richtlinie mit demselben Ursprung. Eine Webanwendung, die XMLHttpRequest oder Fetch verwendet, konnte daher nur HTTP-Anforderungen an ihre eigene Domäne senden.

Quelle: https://developer.mozilla.org/en-US/docs/Web/HTTP/Access_control_CORS

Sie müssen den HTTP-Header Access-Control-Allow-Origin: * von Ihrer Serverseite aus senden .

Wenn Sie Apache als HTTP-Server verwenden, können Sie es wie folgt zu Ihrer Apache-Konfigurationsdatei hinzufügen:

<IfModule mod_headers.c>
    Header set Access-Control-Allow-Origin "*"
</IfModule>

Mod_headers ist in Apache standardmäßig aktiviert. Sie können jedoch sicherstellen, dass es aktiviert ist, indem Sie Folgendes ausführen:

 a2enmod headers
Tadej
quelle
Wo finde ich meine Apache-Konfigurationsdatei?
Shubham Arya
@ ShubhamArya unter Linux Debian der Standardspeicherort ist:/etc/apache2/apache2.conf
Tadej
Wo finde ich es in Windows?
Shubham Arya
10

Wenn Sie eine Chrome-Erweiterung schreiben

Sie müssen manifest.jsondie Berechtigungen für Ihre Domain (s) hinzufügen .

"permissions": [
   "http://example.com/*",
   "https://example.com/*"
]
freedev
quelle
1
Überprüfen Sie auch, ob Sie www Präfix
Vlas Bashynskyi
8

Wenn Sie zufällig einen IIS-Server verwenden. Sie können die folgenden Header in der Option HTTP-Anforderungsheader festlegen.

Access-Control-Allow-Origin:*
Access-Control-Allow-Methods: 'HEAD, GET, POST, PUT, PATCH, DELETE'
Access-Control-Allow-Headers: 'Origin, Content-Type, X-Auth-Token';

mit diesem alle Post, bekommen usw., wird gut funktionieren.

Sunil Kumar
quelle
5

In PHP können Sie die Header hinzufügen:

<?php
header ("Access-Control-Allow-Origin: *");
header ("Access-Control-Expose-Headers: Content-Length, X-JSON");
header ("Access-Control-Allow-Methods: GET, POST, PATCH, PUT, DELETE, OPTIONS");
header ("Access-Control-Allow-Headers: *");
...
atiruz
quelle
Danke, es hat bei mir funktioniert! in Tests und Produktionsumgebung. Sogar mit https: //
Jose Seie
1
@atiruz Danke für die Lösung. Dies funktioniert, als ich die Zeile hinzugefügt habeheader ("Access-Control-Expose-Headers: Content-Length, X-JSON");
Silambarasan RD
5

So beheben Sie Probleme zwischen Ursprungsanforderungen in einer Node JS-Anwendung:

npm i cors

Und fügen Sie einfach die folgenden Zeilen hinzu app.js

let cors = require('cors')
app.use(cors())
Rohit Parte
quelle
3
Dies funktioniert nur in Express JS Apps, nicht in allen Node Apps
DrCord
3

In meiner Apache VirtualHost-Konfigurationsdatei habe ich folgende Zeilen hinzugefügt:

Header always set Access-Control-Allow-Origin "*"
Header always set Access-Control-Allow-Methods "POST, GET, OPTIONS, DELETE, PUT"
Header always set Access-Control-Max-Age "1000"
Header always set Access-Control-Allow-Headers "x-requested-with, Content-Type, origin, authorization, accept, client-security-token"

RewriteEngine On
RewriteCond %{REQUEST_METHOD} OPTIONS
RewriteRule ^(.*)$ $1 [R=200,L]
Umarmungen
quelle
3

Für diejenigen, die Lambda Integrated Proxy mit API-Gateway verwenden . Sie müssen Ihre Lambda-Funktion so konfigurieren, als würden Sie Ihre Anforderungen direkt an sie senden. Dies bedeutet, dass die Funktion die Antwortheader ordnungsgemäß einrichten sollte. (Wenn Sie benutzerdefinierte Lambda-Funktionen verwenden, wird dies vom API-Gateway übernommen.)

//In your lambda's index.handler():
exports.handler = (event, context, callback) => {
     //on success:
     callback(null, {
           statusCode: 200,
           headers: {
                "Access-Control-Allow-Origin" : "*"
           }
     }
}
Xu Chen
quelle
1
Ich möchte mich auch einmischen und ein großes Problem erwähnen, von dem ich glaube, dass es keine AWS-Dokumente gibt. Angenommen, Sie verwenden das API-Gateway, um Ihre Lambda-Funktion zu vertreten, und Sie verwenden eine API in dieser Lambda-Funktion. Wenn diese API einen Erfolgscode für Nicht-200 zurückgibt und Sie den Erfolgscode für Nicht-200 nicht zur Methodenantwort im API-Gateway hinzugefügt haben, wird ein Fehler angezeigt und Ihre erfolgreiche Antwort wird nicht angezeigt . Beispiele hierfür: Sendgrid und Twilio haben Nicht-200-Erfolgscodes.
Stephen Tetreault
3

Ich denke, das Deaktivieren von CORS aus Chrome ist kein guter Weg , denn wenn Sie es in ionic verwenden, wird das Problem in Mobile Build sicherlich erneut auftreten.

Also besser in deinem Backend reparieren.

Zunächst müssen Sie im Header Folgendes festlegen:

  • Header ('Access-Control-Allow-Origin: *');
  • Header ('Header-Set Access-Control-Allow-Header: "Origin, X-Requested-With, Inhaltstyp, Accept"');

Und wenn sich die API wie GET und POST verhält, dann setzen Sie auch in Ihrem Header-

if ($ _SERVER ['REQUEST_METHOD'] == 'OPTIONS') {if (isset ($ _ SERVER ['HTTP_ACCESS_CONTROL_REQUEST_METHOD'])) header ("Access-Control-Allow-Methoden: GET, POST, OPTIONS");
if (isset ($ _ SERVER ['HTTP_ACCESS_CONTROL_REQUEST_HEADERS'])) header ("Access-Control-Allow-Header:
{$ _SERVER ['HTTP_ACCESS_CONTROL_REQUEST_HEADERS']}"); Ausfahrt (0); }}

Shubham Pandey
quelle
3

Eine sehr häufige Ursache für diesen Fehler könnte sein, dass die Host-API die Anforderung einer http-Methode (z. B. PUT) zugeordnet hat und der API-Client die API mit einer anderen http-Methode (z. B. POST oder GET) aufruft.

Christian Nwafor
quelle
Ich habe CORS ordnungsgemäß auf meinem Server implementiert, aber ich habe vergessen, die PUTMethode hinzuzufügen
fguillen
3

Unser Team sieht dies gelegentlich mit Vue, Axios und einem C # WebApi. Durch Hinzufügen eines Routenattributs zu dem Endpunkt, den Sie treffen möchten, wird dies für uns behoben.

[Route("ControllerName/Endpoint")]
[HttpOptions, HttpPost]
public IHttpActionResult Endpoint() { }
w00ngy
quelle
Wir sind uns nicht sicher warum. Lol. Wenn jemand mich wissen lässt!
w00ngy
1

Ich habe mit diesem Problem konfrontiert, als der DNS-Server auf 8.8.8.8 (google's) eingestellt war. Eigentlich war das Problem im Router, meine Anwendung versuchte, über Google eine Verbindung zum Server herzustellen, nicht lokal (für meinen speziellen Fall). Ich habe 8.8.8.8 entfernt und dies hat das Problem gelöst. Ich weiß, dass dieses Problem durch die CORS-Einstellungen behoben wurde, aber vielleicht hat jemand die gleichen Probleme wie ich

Kirill Gusyatin
quelle
1

Ich verwende AWS sdk für Uploads. Nachdem ich einige Zeit online gesucht habe, bin ich auf diesen Thread gestoßen. Dank @lsimoneau 45581857 stellte sich heraus, dass genau das Gleiche geschah. Ich habe meine Anforderungs-URL einfach auf die Region in meinem Bucket gerichtet, indem ich die Regionsoption angehängt habe, und es hat funktioniert.

 const s3 = new AWS.S3({
 accessKeyId: config.awsAccessKeyID,
 secretAccessKey: config.awsSecretAccessKey,
 region: 'eu-west-2'  // add region here });
davyCode
quelle
0

Zu den eigenständigen Distributionen von GeoServer gehört der Jetty-Anwendungsserver. Aktivieren Sie CORS (Cross-Origin Resource Sharing), damit JavaScript-Anwendungen außerhalb Ihrer eigenen Domäne GeoServer verwenden können.

Kommentieren Sie Folgendes <filter>und <filter-mapping>aus webapps / geoserver / WEB-INF / web.xml aus:

<web-app>
  <filter>
      <filter-name>cross-origin</filter-name>
      <filter-class>org.eclipse.jetty.servlets.CrossOriginFilter</filter-class>
  </filter>
  <filter-mapping>
      <filter-name>cross-origin</filter-name>
      <url-pattern>/*</url-pattern>
  </filter-mapping>
</web-app>
Yassine Ech-Charafi
quelle
Das hat nichts zum Antwortheader hinzugefügt, also hat es nicht funktioniert
JollyRoger
1
Ich benutze GeoServer nicht, aber dieser Clip hat mir geholfen, die Einstellungen zu kennen, die ich für die App verwenden sollte, die den Anruf erhält.
Matt Felzani
0

Es ist einfach, dieses Problem mit wenigen Schritten zu lösen, ohne sich um irgendetwas kümmern zu müssen. Bitte folgen Sie den Schritten, um es zu lösen.

  1. offen ( https://www.npmjs.com/package/cors#enabling-cors-pre-flight )
  2. Gehen Sie zur Installation und kopieren Sie den Befehl npm install cors, um ihn über das Knotenterminal zu installieren
  3. Gehen Sie zu Einfache Verwendung (Alle CORS-Anforderungen aktivieren), indem Sie scrollen. Kopieren Sie dann die vollständige Deklaration und fügen Sie sie in Ihr Projekt ein. Führen Sie sie aus. Dies funktioniert auf jeden Fall. Kopieren Sie den Kommentarcode und fügen Sie sie in Ihre app.js oder eine andere ein Projektieren und probieren Sie es aus. Dies wird funktionieren. Dadurch wird jede gemeinsame Nutzung von Ressourcen zwischen verschiedenen Freischaltungen freigeschaltet. So können wir zwischen Aufschlägen für Ihre Verwendung wechseln
Rahul sah
quelle
1
var express = erfordern ('express') var cors = erfordern ('cors') var app = express () app.use (cors ()) app.get ('/ products /: id', Funktion (req, res, next) {res.json ({msg: 'Dies ist CORS-fähig für alle Ursprünge!'})}) app.listen (80, function () {console.log ('CORS-fähiger Webserver überwacht Port 80' )})
Rahul sah
-1

Etwas, das sehr leicht zu übersehen ist ...

Klicken Sie im Solution Explorer mit der rechten Maustaste auf das API-Projekt. Setzen Sie im Eigenschaftenfenster 'Anonyme Authentifizierung' auf Aktiviert !!!

Wir s
quelle
-8

Deaktivieren Sie die Chrome-Sicherheit. Erstellen Sie eine Chrome-Verknüpfung mit der rechten Maustaste -> Eigenschaften -> Ziel und fügen Sie dieses "C: \ Programme (x86) \ Google \ Chrome \ Application \ chrome.exe" --disable-web-security --user ein -data-dir = "c: / chromedev"

Nithin
quelle