Anforderungsheaderfeld Access-Control-Allow-Headers ist in der Preflight-Antwort für sich genommen nicht zulässig

234

Ich bin mehrmals auf CORS-Probleme gestoßen und kann sie normalerweise beheben, aber ich möchte sie wirklich verstehen, indem ich dies anhand eines MEAN-Stack-Paradigmas sehe.

Früher habe ich einfach Middleware in meinen Express-Server eingefügt, um diese Dinge abzufangen, aber es sieht so aus, als ob es eine Art Pre-Hook gibt, der meine Anfragen fehlerhaft macht.

Anforderungsheaderfeld Access-Control-Allow-Headers wird von Access-Control-Allow-Headern in der Preflight-Antwort nicht zugelassen

Ich nahm an, dass ich das tun könnte:

app.use(function(req, res, next) {
  res.header("Access-Control-Allow-Headers","*")
})

oder das Äquivalent, aber das scheint es nicht zu beheben. Ich habe es natürlich auch versucht

app.use(function(req, res, next) {
  res.header("Access-Control-Allow-Headers","Access-Control-Allow-Headers")
})

Immer noch kein Glück.

Mibbit
quelle

Antworten:

245

Wenn Sie mit benutzerdefinierten Anforderungsheadern herumspielen, erhalten Sie einen CORS-Preflight. Dies ist eine Anforderung, die das HTTP- OPTIONSVerb verwendet und mehrere Header enthält, von denen einer Access-Control-Request-Headersdie Header auflistet, die der Client in die Anforderung aufnehmen möchte.

Sie müssen auf diesen CORS-Preflight mit den entsprechenden CORS-Headern antworten, damit dies funktioniert. Eines davon ist in der Tat Access-Control-Allow-Headers. Dieser Header muss dieselben Werte enthalten wie der Access-Control-Request-HeadersHeader (oder mehr).

https://fetch.spec.whatwg.org/#http-cors-protocol erläutert dieses Setup ausführlicher.

Anne
quelle
41
Wenn Sie Chrome verwenden und nicht sicher sind, welche Header angefordert werden, verwenden Sie die Entwicklerkonsole, wählen Sie im Netzwerk den Anruf aus, und Sie können anzeigen, von welchen Headern angefordert wirdAccess-Control-Request-Headers
Lionel Morrison
5
Die Developer Console-Option ist gut. Sie können auch finden, was Sie benötigen, indem Sie Zugriff auf das Anforderungsobjekt auf dem Server erhalten und die Werte für die Header, insbesondere aber den Headerwert für "Access-Control-Request-Headers", ausgeben. Kopieren Sie diese dann in Ihre response.setHeader ("Access-Control-Allow-Headers", "{hier einfügen}")
Software Prophets
7
Beispiel bitte!
Demodave
5
@ Demodave ein Beispiel dafür war für michheader("Access-Control-Allow-Headers: Content-Type")
Joshua Duxbury
1
@ LionelMorrison, Verwendung von Chrome Dev Tools zum Abgleichen von Headern. gut erklärt !!!
Savina Chandla
119

Dies ist, was Sie hinzufügen müssen, damit es funktioniert.

response.setHeader("Access-Control-Allow-Origin", "*");
response.setHeader("Access-Control-Allow-Credentials", "true");
response.setHeader("Access-Control-Allow-Methods", "GET,HEAD,OPTIONS,POST,PUT");
response.setHeader("Access-Control-Allow-Headers", "Access-Control-Allow-Headers, Origin,Accept, X-Requested-With, Content-Type, Access-Control-Request-Method, Access-Control-Request-Headers");

Der Browser sendet eine Preflight-Anforderung (mit dem Methodentyp OPTIONS), um zu überprüfen, ob der auf dem Server gehostete Dienst vom Browser in einer anderen Domäne aus aufgerufen werden darf. Als Antwort auf die Preflight-Anfrage, wenn Sie die obigen Header einfügen, versteht der Browser, dass es in Ordnung ist, weitere Anrufe zu tätigen, und ich erhalte eine gültige Antwort auf meinen tatsächlichen GET / POST-Anruf. Sie können die Domäne, auf die der Zugriff gewährt wird, einschränken, indem Sie Access-Control-Allow-Origin "," localhost, xvz.com "anstelle von * verwenden. (* gewährt Zugriff auf alle Domänen)

manische Arora
quelle
7
Sie können nicht *für ...-Originund truefür kombinieren ...-Credentials. Es schlägt nicht für Anforderungen ohne Anmeldeinformationen fehl, aber es funktioniert auch nicht für Anforderungen mit Anmeldeinformationen. Siehe den Link, den ich in meiner Antwort gepostet habe.
Anne
Danke Manish Arora, ich habe deine Lösung in meiner API verwendet und es hat funktioniert. HttpContext.Response.Headers.Add ("Zugriffssteuerungs-Zulassungsmethoden", "GET, HEAD, OPTIONS, POST, PUT"); HttpContext.Response.Headers.Add ("Zugriffssteuerungs-Zulassungs-Header", "Zugriffssteuerungs-Zulassungs-Header", Ursprung, Akzeptieren, X-Angefordert-Mit, Inhaltstyp, Zugriffssteuerungs-Anforderungsmethode, Zugriff -Control-Request-Headers "); HttpContext.Response.Headers.Add ("Access-Control-Allow-Origin", " localhost: 4200" );
Ramakrishnankt
1
Dies bedeutet, dass auf der Serverseite all dieses Munging des Antwortheaders aufgrund von "Preflight" erforderlich ist. Warum? Speziell für perfekt standardmäßige Header? Nachdem ich HTTP für eine Weile benutzt habe, ist es für mich neu, dass so viel Boilerplate benötigt wird.
Samantha Atkins
@manish Ich hatte einen anderen Wertesatz für Access-Control-Allow-Header, der nicht funktionierte. Ihre Werte haben es getan. Vielen Dank, dass Sie Zeit und Frust gespart haben.
Azakgaim
Gibt es eine Möglichkeit, einige Header mit einem Platzhalter zu versehen? Ist es eine schlechte Idee, alle Header mit einem Platzhalter zu versehen? Wie zum Beispiel response.setHeader("Access-Control-Allow-Headers", "*")? Was bedeutet dies für die Sicherheit?
Vadorequest
78

Dieses Problem wurde mit gelöst

 "Origin, X-Requested-With, Content-Type, Accept, Authorization"

Besonders in meinem Projekt (express.js / nodejs)

app.use(function(req, res, next) {
  res.header("Access-Control-Allow-Origin", "*");
  res.header("Access-Control-Allow-Methods", "GET,HEAD,OPTIONS,POST,PUT");
  res.header("Access-Control-Allow-Headers", "Origin, X-Requested-With, Content-Type, Accept, Authorization");
  next();
});

Aktualisieren:

Jedes Mal Fehler: Access-Control-Allow-Headers is not allowed by itself in preflight responseFehler Sie können sehen, was mit dem Chrome Developer Tool falsch ist :
Geben Sie hier die Bildbeschreibung ein

obiger Fehler fehlt Content-Typeso hinzufügen Zeichenfolge Content-TypezuAccess-Control-Allow-Headers

nguyên
quelle
1
Dies wird nicht für alle funktionieren. Der Wert für Access-Control-Request-Header kann je nach Umgebung variieren. Erhalten Sie Zugriff auf das Anforderungsobjekt auf dem Server und sichern Sie die Werte für den Header "Access-Control-Request-Headers". Dann kopiere / füge dies in deine response.setHeader ein ("Access-Control-Allow-Headers", "{hier einfügen}")
Software Prophets
1
Stellen Sie außerdem sicher, dass Sie Authorization auf amerikanische und nicht auf britische Weise buchstabieren. Das ist eine halbe Stunde meines Lebens, ich werde nicht zurückkommen. Danke USA! [Seufzer]
geoidesic
14

Die akzeptierte Antwort ist in Ordnung, aber ich hatte Schwierigkeiten, sie zu verstehen. Hier ist ein einfaches Beispiel, um dies zu verdeutlichen.

In meiner Ajax-Anfrage hatte ich einen Standard-Authorization-Header.

$$(document).on('ajaxStart', function(e){
var auth_token = localStorage.getItem(SB_TOKEN_MOBILE);
if( auth_token ) {
    var xhr = e.detail.xhr;

    xhr.setRequestHeader('**Authorization**', 'Bearer ' + auth_token);
}

Dieser Code erzeugt den Fehler in der Frage. Was ich auf meinem nodejs-Server tun musste, war, Autorisierung in zulässigen Headern hinzuzufügen:

res.setHeader('Access-Control-Allow-Headers', 'X-Requested-With,content-type,**Authorization**');
user732456
quelle
6

Zu den anderen Antworten hinzufügen. Ich hatte das gleiche Problem und dies ist der Code, den ich in meinem Express-Server verwendet habe, um REST-Aufrufe zuzulassen:

app.all('*', function(req, res, next) {
  res.header('Access-Control-Allow-Origin', 'URLs to trust of allow');
  res.header('Access-Control-Allow-Methods', 'GET, POST, OPTIONS, PUT, PATCH, DELETE');
  res.header('Access-Control-Allow-Headers', 'Content-Type');
  if ('OPTIONS' == req.method) {
  res.sendStatus(200);
  } else {
    next();
  }
});

Dieser Code fängt im Grunde alle Anforderungen ab und fügt die CORS-Header hinzu. Fahren Sie dann mit meinen normalen Routen fort. Wenn eine OPTIONS-Anforderung vorliegt, antwortet diese nur mit den CORS-Headern.

BEARBEITEN: Ich habe dieses Update für zwei separate NodeJS Express-Server auf demselben Computer verwendet. Am Ende habe ich das Problem mit einem einfachen Proxyserver behoben.

Luke Kroon
quelle
Vielen Dank! Können Sie erläutern, wie Sie einen einfachen Proxyserver verwendet haben?
austin_ce
5

Ich bin gerade selbst auf dieses Problem gestoßen. Stellen Sie im Kontext von ASP.NET sicher, dass Ihre Web.config folgendermaßen aussieht:

  <system.webServer>
<modules>
  <remove name="FormsAuthentication" />
</modules>

<handlers>
  <remove name="ExtensionlessUrlHandler-Integrated-4.0" />
  <!--<remove name="OPTIONSVerbHandler"/>-->
  <remove name="TRACEVerbHandler" />
  <!--
  <add name="ExtensionlessUrlHandler-Integrated-4.0" path="*." verb="*" type="System.Web.Handlers.TransferRequestHandler" preCondition="integratedMode,runtimeVersionv4.0" />
  -->
</handlers>

<httpProtocol>
  <customHeaders>
    <add name="Access-Control-Allow-Origin" value="*" />
    <add name="Access-Control-Allow-Headers" value="Content-Type, Authorization" />
    <add name="Access-Control-Allow-Methods" value="GET, POST, PUT, DELETE, OPTIONS" />
  </customHeaders>
</httpProtocol>

Beachten Sie den Autorisierungswert für den Access-Control-Allow-HeadersSchlüssel. Mir fehlte der Autorisierungswert. Diese Konfiguration löst mein Problem.

Josh Siegl
quelle
5

Sehr gut, ich habe dies für ein Silex-Projekt verwendet

$app->after(function (Request $request, Response $response) {
        $response->headers->set('Access-Control-Allow-Origin', '*');
        $response->headers->set("Access-Control-Allow-Credentials", "true");
        $response->headers->set("Access-Control-Allow-Methods", "GET,HEAD,OPTIONS,POST,PUT");
        $response->headers->set("Access-Control-Allow-Headers", "Origin, X-Requested-With, Content-Type, Accept, Authorization");
    });
Al Kativo
quelle
2
Während dieser Code die Frage möglicherweise beantwortet, würde die Bereitstellung eines zusätzlichen Kontexts darüber, wie und / oder warum das Problem gelöst wird, den langfristigen Wert der Antwort verbessern.
Badacadabra
4

In Chrome:

Das Anforderungsheaderfeld X-Requested-With wird von Access-Control-Allow-Headern in der Preflight-Antwort nicht zugelassen.

Für mich wurde dieser Fehler durch ein nachfolgendes Leerzeichen in der URL dieses Aufrufs ausgelöst .

jQuery.getJSON( url, function( response, status, xhr ) {
   ...
}
user3248255
quelle
3

Nur um hinzuzufügen, dass Sie diese Header auch in die Webpack-Konfigurationsdatei einfügen können. Ich brauchte sie wie in meinem Fall, als ich den Webpack Dev Server ausführte.

devServer: {
    headers: {
      "Access-Control-Allow-Origin": "*",
      "Access-Control-Allow-Credentials": "true",
      "Access-Control-Allow-Methods": "GET,HEAD,OPTIONS,POST,PUT",
      "Access-Control-Allow-Headers": "Origin, X-Requested-With, Content-Type, Accept, Authorization"
},
Janne
quelle
3

res.setHeader ('Access-Control-Allow-Headers', '*');

Kanomdook
quelle
2

Ich habe den Fehler erhalten, den das OP mit Django, React und der Django-Cors-Header-Bibliothek angegeben hat. Gehen Sie wie folgt vor, um das Problem mit diesem Stapel zu beheben:

Fügen Sie in settings.py das Folgende gemäß der offiziellen Dokumentation hinzu .

from corsheaders.defaults import default_headers

CORS_ALLOW_HEADERS = default_headers + (
'YOUR_HEADER_NAME',
)
Eric
quelle
2

Dieses Problem tritt auf, wenn wir einen benutzerdefinierten Header für die Anforderung erstellen. Diese Anforderung verwendet die HTTP OPTIONS und enthält mehrere Header.

Der erforderliche Header für diese Anforderung ist Access-Control-Request-Headers, der Teil des Antwortheaders sein und eine Anforderung von allen Ursprüngen zulassen sollte. Manchmal braucht es Content-Typeauch im Header der Antwort. Ihr Antwortheader sollte also so sein -

response.header("Access-Control-Allow-Origin", "*"); // allow request from all origin
response.header("Access-Control-Allow-Methods", "GET,HEAD,OPTIONS,POST,PUT");
response.header("Access-Control-Allow-Headers", "Access-Control-Allow-Headers, Origin, X-Requested-With, Content-Type, Accept, Authorization");
Sai Prateek
quelle
1

Beim Post-API-Aufruf senden wir Daten im Anforderungshauptteil. Wenn wir also Daten senden, indem wir einem API-Aufruf einen zusätzlichen Header hinzufügen. Dann erfolgt zuerst der API-Aufruf OPTIONS und dann der Aufruf nach dem Aufruf. Daher müssen Sie zuerst den OPTION-API-Aufruf verarbeiten.

Sie können das Problem beheben, indem Sie einen Filter schreiben, in dem Sie nach API-Aufrufen für Optionsaufrufe suchen und den Status 200 OK zurückgeben müssen. Unten ist der Beispielcode:

package com.web.filter;

import java.io.IOException;

import javax.servlet.Filter;
import javax.servlet.FilterChain;
import javax.servlet.FilterConfig;
import javax.servlet.ServletException;
import javax.servlet.ServletRequest;
import javax.servlet.ServletResponse;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;

import org.apache.catalina.connector.Response;

public class CustomFilter implements Filter {
    public void doFilter(ServletRequest req, ServletResponse res, FilterChain chain)
            throws IOException, ServletException {
        HttpServletResponse response = (HttpServletResponse) res;
        HttpServletRequest httpRequest = (HttpServletRequest) req;
        response.setHeader("Access-Control-Allow-Origin", "*");
        response.setHeader("Access-Control-Allow-Methods", "POST, GET, PUT, OPTIONS, DELETE");
        response.setHeader("Access-Control-Max-Age", "3600");
        response.setHeader("Access-Control-Allow-Headers", "x-requested-with, Content-Type");
        if (httpRequest.getMethod().equalsIgnoreCase("OPTIONS")) {
            response.setStatus(Response.SC_OK);
        }
        chain.doFilter(req, res);
    }

    public void init(FilterConfig filterConfig) {
        // TODO
    }

    public void destroy() {
        // Todo
    }

}
doppelter Piepton
quelle
1

Wenn Sie versuchen, den Anforderungsheadern einen benutzerdefinierten Header hinzuzufügen, müssen Sie dem Server mitteilen, dass ein bestimmter Header zulässig ist. Der Ort dafür ist in der Klasse, die die Anforderungen filtert. In dem unten gezeigten Beispiel lautet der benutzerdefinierte Headername "Typ":

public class CorsFilter implements Filter {
    @Override
    public void doFilter(ServletRequest req, ServletResponse res, FilterChain chain) throws IOException, ServletException {
        HttpServletRequest request = (HttpServletRequest) req;
        HttpServletResponse response = (HttpServletResponse) res;
        response.setHeader("Access-Control-Allow-Origin",  request.getHeader("Origin"));
        response.setHeader("Access-Control-Allow-Credentials", "true");
        response.setHeader("Access-Control-Allow-Methods", "GET,PUT,POST,DELETE,PATCH,OPTIONS");
        response.setHeader("Access-Control-Max-Age", "3600");
        response.setHeader("Access-Control-Allow-Headers", "Content-Type, Accept, X-Requested-With, remember-me, Authorization, type ");
        response.setHeader("Access-Control-Expose-Headers","Authorization");
    }
}
Kristina Mojanovska
quelle
1

Nachdem ich fast einen Tag verbracht hatte, fand ich gerade heraus, dass das Hinzufügen der folgenden zwei Codes mein Problem löste.

Fügen Sie dies in die Datei Global.asax ein

protected void Application_BeginRequest()
{
  if (Request.HttpMethod == "OPTIONS")
  {
    Response.StatusCode = (int)System.Net.HttpStatusCode.OK;             
    Response.End();
  }
}

und fügen Sie in der Webkonfiguration Folgendes hinzu

<httpProtocol>
  <customHeaders>
    <add name="Access-Control-Allow-Origin" value="*" />        
    <add name="Access-Control-Allow-Methods" value="*" />
    <add name="Access-Control-Allow-Headers" value="Content-Type, Authorization" />
  </customHeaders>
</httpProtocol>
Biruk Belihu
quelle
1

Auch ich hatte das gleiche Problem in Angular 6. Ich habe das Problem mithilfe des folgenden Codes gelöst. Fügen Sie den Code in die Datei component.ts ein.

import { HttpHeaders } from '@angular/common/http';

headers;

constructor() {
    this.headers = new HttpHeaders();
    this.headers.append('Access-Control-Allow-Headers', 'Authorization');
}

getData() {
    this.http.get(url,this.headers). subscribe (res => {
    // your code here...
})}
Karthi Der Programmierer
quelle
0

Das gleiche Problem, mit dem ich konfrontiert war.

Ich habe eine einfache Änderung vorgenommen.

  <modulename>.config(function($httpProvider){
    delete $httpProvider.defaults.headers.common['X-Requested-With'];
});
Shashikant Pandit
quelle
0

Es ist klar, dass die Autorisierung in der API nicht zulässig ist. Set
Access-Control-Allow-Header setzen: "Inhaltstyp, Autorisierung"

Rajesh Yadav
quelle
0
const express = require('express')
const cors = require('cors')
const app = express()

app.get('/with-cors', cors(), (req, res, next) => {
  res.json({ msg: 'WHOAH with CORS it works! 🔝 🎉' })
})

Das Hinzufügen von Cors in der Get-Funktion hat bei mir funktioniert

Ayman OUKACHA
quelle